gh-manager-cli 1.7.0 → 1.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/CHANGELOG.md +7 -0
- package/dist/chunk-OQGG2X5P.js +648 -0
- package/dist/github-TWXF5AWM.js +29 -0
- package/dist/index.js +450 -778
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import {
|
|
3
|
+
__commonJS,
|
|
4
|
+
archiveRepositoryById,
|
|
5
|
+
deleteRepositoryRest,
|
|
6
|
+
fetchViewerOrganizations,
|
|
7
|
+
fetchViewerReposPageUnified,
|
|
8
|
+
getViewerLogin,
|
|
9
|
+
inspectCacheStatus,
|
|
10
|
+
makeClient,
|
|
11
|
+
purgeApolloCacheFiles,
|
|
12
|
+
searchRepositoriesUnified,
|
|
13
|
+
syncForkWithUpstream,
|
|
14
|
+
unarchiveRepositoryById
|
|
15
|
+
} from "./chunk-OQGG2X5P.js";
|
|
6
16
|
|
|
7
17
|
// package.json
|
|
8
18
|
var require_package = __commonJS({
|
|
9
19
|
"package.json"(exports, module) {
|
|
10
20
|
module.exports = {
|
|
11
21
|
name: "gh-manager-cli",
|
|
12
|
-
version: "1.
|
|
22
|
+
version: "1.8.0",
|
|
13
23
|
private: false,
|
|
14
24
|
description: "Interactive CLI to manage your GitHub repos (personal) with Ink",
|
|
15
25
|
license: "MIT",
|
|
@@ -125,12 +135,12 @@ var require_package = __commonJS({
|
|
|
125
135
|
});
|
|
126
136
|
|
|
127
137
|
// src/index.tsx
|
|
128
|
-
import { render, Box as
|
|
138
|
+
import { render, Box as Box4, Text as Text4 } from "ink";
|
|
129
139
|
import "dotenv/config";
|
|
130
140
|
|
|
131
141
|
// src/ui/App.tsx
|
|
132
|
-
import { useEffect as
|
|
133
|
-
import { Box as
|
|
142
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
|
|
143
|
+
import { Box as Box3, Text as Text3, useApp as useApp2, useStdout as useStdout2, useInput as useInput3 } from "ink";
|
|
134
144
|
import TextInput2 from "ink-text-input";
|
|
135
145
|
|
|
136
146
|
// src/config.ts
|
|
@@ -186,490 +196,23 @@ function storeUIPrefs(patch) {
|
|
|
186
196
|
writeConfig({ ...existing, ui: mergedUI });
|
|
187
197
|
}
|
|
188
198
|
|
|
189
|
-
// src/github.ts
|
|
190
|
-
import { graphql as makeGraphQL } from "@octokit/graphql";
|
|
191
|
-
import { ApolloClient, InMemoryCache, HttpLink, gql } from "@apollo/client/core/index.js";
|
|
192
|
-
import { persistCache } from "apollo3-cache-persist";
|
|
193
|
-
import fs2 from "fs";
|
|
194
|
-
import path2 from "path";
|
|
195
|
-
import envPaths2 from "env-paths";
|
|
196
|
-
function makeClient(token) {
|
|
197
|
-
return makeGraphQL.defaults({
|
|
198
|
-
headers: { authorization: `token ${token}` }
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
async function makeApolloClient(token) {
|
|
202
|
-
try {
|
|
203
|
-
if (typeof globalThis.fetch === "undefined") {
|
|
204
|
-
throw new Error("Fetch API not available. Node 18+ is required.");
|
|
205
|
-
}
|
|
206
|
-
const cache = new InMemoryCache();
|
|
207
|
-
const storage = {
|
|
208
|
-
async getItem(key) {
|
|
209
|
-
try {
|
|
210
|
-
const p = envPaths2("gh-manager-cli").data;
|
|
211
|
-
const file = path2.join(p, "apollo-cache.json");
|
|
212
|
-
return fs2.readFileSync(file, "utf8");
|
|
213
|
-
} catch {
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
async setItem(key, value) {
|
|
218
|
-
try {
|
|
219
|
-
const p = envPaths2("gh-manager-cli").data;
|
|
220
|
-
fs2.mkdirSync(p, { recursive: true });
|
|
221
|
-
const file = path2.join(p, "apollo-cache.json");
|
|
222
|
-
fs2.writeFileSync(file, value, "utf8");
|
|
223
|
-
if (process.platform !== "win32") {
|
|
224
|
-
try {
|
|
225
|
-
fs2.chmodSync(file, 384);
|
|
226
|
-
} catch {
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
} catch {
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
async removeItem(key) {
|
|
233
|
-
try {
|
|
234
|
-
const p = envPaths2("gh-manager-cli").data;
|
|
235
|
-
const file = path2.join(p, "apollo-cache.json");
|
|
236
|
-
fs2.unlinkSync(file);
|
|
237
|
-
} catch {
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
await persistCache({ cache, storage, debounce: 500, maxSize: 5 * 1024 * 1024 });
|
|
242
|
-
const link = new HttpLink({
|
|
243
|
-
uri: "https://api.github.com/graphql",
|
|
244
|
-
fetch: globalThis.fetch,
|
|
245
|
-
headers: { authorization: `Bearer ${token}` }
|
|
246
|
-
});
|
|
247
|
-
const client = new ApolloClient({ cache, link });
|
|
248
|
-
return { client, gql };
|
|
249
|
-
} catch (error) {
|
|
250
|
-
const debug = process.env.GH_MANAGER_DEBUG === "1";
|
|
251
|
-
if (debug) {
|
|
252
|
-
process.stderr.write(`
|
|
253
|
-
\u274C Failed to initialize Apollo Client: ${error.message}
|
|
254
|
-
`);
|
|
255
|
-
if (error.stack) {
|
|
256
|
-
process.stderr.write(`Stack: ${error.stack}
|
|
257
|
-
`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
throw new Error(`Apollo Client initialization failed: ${error.message}`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
async function getViewerLogin(client) {
|
|
264
|
-
const query = (
|
|
265
|
-
/* GraphQL */
|
|
266
|
-
`
|
|
267
|
-
query ViewerLogin {
|
|
268
|
-
viewer {
|
|
269
|
-
login
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
`
|
|
273
|
-
);
|
|
274
|
-
const res = await client(query);
|
|
275
|
-
return res.viewer.login;
|
|
276
|
-
}
|
|
277
|
-
async function fetchViewerReposPage(client, first, after, orderBy, includeForkTracking = true) {
|
|
278
|
-
const sortField = orderBy?.field || "UPDATED_AT";
|
|
279
|
-
const sortDirection = orderBy?.direction || "DESC";
|
|
280
|
-
const query = (
|
|
281
|
-
/* GraphQL */
|
|
282
|
-
`
|
|
283
|
-
query ViewerRepos(
|
|
284
|
-
$first: Int!
|
|
285
|
-
$after: String
|
|
286
|
-
$sortField: RepositoryOrderField!
|
|
287
|
-
$sortDirection: OrderDirection!
|
|
288
|
-
) {
|
|
289
|
-
rateLimit {
|
|
290
|
-
limit
|
|
291
|
-
remaining
|
|
292
|
-
resetAt
|
|
293
|
-
}
|
|
294
|
-
viewer {
|
|
295
|
-
repositories(
|
|
296
|
-
ownerAffiliations: OWNER
|
|
297
|
-
first: $first
|
|
298
|
-
after: $after
|
|
299
|
-
orderBy: { field: $sortField, direction: $sortDirection }
|
|
300
|
-
) {
|
|
301
|
-
totalCount
|
|
302
|
-
pageInfo {
|
|
303
|
-
endCursor
|
|
304
|
-
hasNextPage
|
|
305
|
-
}
|
|
306
|
-
nodes {
|
|
307
|
-
id
|
|
308
|
-
name
|
|
309
|
-
nameWithOwner
|
|
310
|
-
description
|
|
311
|
-
visibility
|
|
312
|
-
isPrivate
|
|
313
|
-
isFork
|
|
314
|
-
isArchived
|
|
315
|
-
stargazerCount
|
|
316
|
-
forkCount
|
|
317
|
-
primaryLanguage {
|
|
318
|
-
name
|
|
319
|
-
color
|
|
320
|
-
}
|
|
321
|
-
updatedAt
|
|
322
|
-
pushedAt
|
|
323
|
-
diskUsage
|
|
324
|
-
${includeForkTracking ? `
|
|
325
|
-
parent {
|
|
326
|
-
nameWithOwner
|
|
327
|
-
defaultBranchRef {
|
|
328
|
-
name
|
|
329
|
-
target {
|
|
330
|
-
... on Commit {
|
|
331
|
-
history(first: 0) {
|
|
332
|
-
totalCount
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
defaultBranchRef {
|
|
339
|
-
name
|
|
340
|
-
target {
|
|
341
|
-
... on Commit {
|
|
342
|
-
history(first: 0) {
|
|
343
|
-
totalCount
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}` : `
|
|
348
|
-
parent {
|
|
349
|
-
nameWithOwner
|
|
350
|
-
}
|
|
351
|
-
defaultBranchRef { name }
|
|
352
|
-
`}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
`
|
|
358
|
-
);
|
|
359
|
-
const res = await client(query, {
|
|
360
|
-
first,
|
|
361
|
-
after: after ?? null,
|
|
362
|
-
sortField,
|
|
363
|
-
sortDirection
|
|
364
|
-
});
|
|
365
|
-
const data = res.viewer.repositories;
|
|
366
|
-
return {
|
|
367
|
-
nodes: data.nodes,
|
|
368
|
-
endCursor: data.pageInfo.endCursor,
|
|
369
|
-
hasNextPage: data.pageInfo.hasNextPage,
|
|
370
|
-
totalCount: data.totalCount,
|
|
371
|
-
rateLimit: res.rateLimit
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
async function fetchViewerReposPageUnified(token, first, after, orderBy, includeForkTracking = true, fetchPolicy = "cache-first") {
|
|
375
|
-
const isApolloEnabled = true;
|
|
376
|
-
const debug = process.env.GH_MANAGER_DEBUG === "1";
|
|
377
|
-
if (debug) {
|
|
378
|
-
console.log(`\u{1F50D} Apollo enabled: ${isApolloEnabled}, Policy: ${fetchPolicy}, After: ${after || "null"}`);
|
|
379
|
-
}
|
|
380
|
-
try {
|
|
381
|
-
if (isApolloEnabled) {
|
|
382
|
-
if (debug) console.log("\u{1F680} Attempting Apollo Client...");
|
|
383
|
-
const ap = await makeApolloClient(token);
|
|
384
|
-
const sortField = orderBy?.field || "UPDATED_AT";
|
|
385
|
-
const sortDirection = orderBy?.direction || "DESC";
|
|
386
|
-
const q = ap.gql`
|
|
387
|
-
query ViewerRepos($first: Int!, $after: String, $sortField: RepositoryOrderField!, $sortDirection: OrderDirection!) {
|
|
388
|
-
rateLimit { limit remaining resetAt }
|
|
389
|
-
viewer {
|
|
390
|
-
repositories(ownerAffiliations: OWNER, first: $first, after: $after, orderBy: { field: $sortField, direction: $sortDirection }) {
|
|
391
|
-
totalCount
|
|
392
|
-
pageInfo { endCursor hasNextPage }
|
|
393
|
-
nodes {
|
|
394
|
-
id
|
|
395
|
-
name
|
|
396
|
-
nameWithOwner
|
|
397
|
-
description
|
|
398
|
-
visibility
|
|
399
|
-
isPrivate
|
|
400
|
-
isFork
|
|
401
|
-
isArchived
|
|
402
|
-
stargazerCount
|
|
403
|
-
forkCount
|
|
404
|
-
primaryLanguage { name color }
|
|
405
|
-
updatedAt
|
|
406
|
-
pushedAt
|
|
407
|
-
diskUsage
|
|
408
|
-
${includeForkTracking ? `
|
|
409
|
-
parent { nameWithOwner defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } } }
|
|
410
|
-
defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } }` : `
|
|
411
|
-
parent { nameWithOwner }
|
|
412
|
-
defaultBranchRef { name }`}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
`;
|
|
418
|
-
const startTime = Date.now();
|
|
419
|
-
const res = await ap.client.query({
|
|
420
|
-
query: q,
|
|
421
|
-
variables: { first, after: after ?? null, sortField, sortDirection },
|
|
422
|
-
fetchPolicy
|
|
423
|
-
});
|
|
424
|
-
const duration = Date.now() - startTime;
|
|
425
|
-
if (debug) {
|
|
426
|
-
console.log(`\u26A1 Apollo query completed in ${duration}ms`);
|
|
427
|
-
console.log(`\u{1F4CA} From cache: ${res.loading === false && duration < 50 ? "YES" : "NO"}`);
|
|
428
|
-
console.log(`\u{1F504} Network status: ${res.networkStatus}`);
|
|
429
|
-
}
|
|
430
|
-
const data = res.data.viewer.repositories;
|
|
431
|
-
return {
|
|
432
|
-
nodes: data.nodes,
|
|
433
|
-
endCursor: data.pageInfo.endCursor,
|
|
434
|
-
hasNextPage: data.pageInfo.hasNextPage,
|
|
435
|
-
totalCount: data.totalCount,
|
|
436
|
-
rateLimit: res.data.rateLimit
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
} catch (e) {
|
|
440
|
-
if (debug) console.log(`\u274C Apollo failed, falling back to Octokit:`, e.message);
|
|
441
|
-
}
|
|
442
|
-
if (debug) console.log("\u{1F4E1} Using Octokit fallback...");
|
|
443
|
-
const octo = makeClient(token);
|
|
444
|
-
return fetchViewerReposPage(octo, first, after, orderBy, includeForkTracking);
|
|
445
|
-
}
|
|
446
|
-
async function searchRepositoriesUnified(token, viewer, text, first, after, sortKey = "UPDATED_AT", sortDir = "DESC", includeForkTracking = true, fetchPolicy = "network-only") {
|
|
447
|
-
const q = `${text} user:${viewer} in:name,description fork:true`;
|
|
448
|
-
try {
|
|
449
|
-
const ap = await makeApolloClient(token);
|
|
450
|
-
const queryDoc = ap.gql`
|
|
451
|
-
query SearchRepos($q: String!, $first: Int!, $after: String) {
|
|
452
|
-
rateLimit { limit remaining resetAt }
|
|
453
|
-
search(query: $q, type: REPOSITORY, first: $first, after: $after) {
|
|
454
|
-
repositoryCount
|
|
455
|
-
pageInfo { endCursor hasNextPage }
|
|
456
|
-
nodes {
|
|
457
|
-
... on Repository {
|
|
458
|
-
id
|
|
459
|
-
name
|
|
460
|
-
nameWithOwner
|
|
461
|
-
description
|
|
462
|
-
visibility
|
|
463
|
-
isPrivate
|
|
464
|
-
isFork
|
|
465
|
-
isArchived
|
|
466
|
-
stargazerCount
|
|
467
|
-
forkCount
|
|
468
|
-
primaryLanguage { name color }
|
|
469
|
-
updatedAt
|
|
470
|
-
pushedAt
|
|
471
|
-
diskUsage
|
|
472
|
-
${includeForkTracking ? `
|
|
473
|
-
parent { nameWithOwner defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } } }
|
|
474
|
-
defaultBranchRef { name target { ... on Commit { history(first: 0) { totalCount } } } }` : `
|
|
475
|
-
parent { nameWithOwner }
|
|
476
|
-
defaultBranchRef { name }`}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
`;
|
|
482
|
-
const res = await ap.client.query({
|
|
483
|
-
query: queryDoc,
|
|
484
|
-
variables: { q, first, after: after ?? null },
|
|
485
|
-
fetchPolicy
|
|
486
|
-
});
|
|
487
|
-
const data = res.data.search;
|
|
488
|
-
return {
|
|
489
|
-
nodes: data.nodes,
|
|
490
|
-
endCursor: data.pageInfo.endCursor,
|
|
491
|
-
hasNextPage: data.pageInfo.hasNextPage,
|
|
492
|
-
totalCount: data.repositoryCount,
|
|
493
|
-
rateLimit: res.data.rateLimit
|
|
494
|
-
};
|
|
495
|
-
} catch (e) {
|
|
496
|
-
const debug = process.env.GH_MANAGER_DEBUG === "1";
|
|
497
|
-
if (debug) {
|
|
498
|
-
process.stderr.write(`
|
|
499
|
-
\u274C Search failed: ${e.message}
|
|
500
|
-
`);
|
|
501
|
-
if (e.graphQLErrors) {
|
|
502
|
-
process.stderr.write(`GraphQL errors: ${JSON.stringify(e.graphQLErrors, null, 2)}
|
|
503
|
-
`);
|
|
504
|
-
}
|
|
505
|
-
if (e.networkError) {
|
|
506
|
-
process.stderr.write(`Network error: ${e.networkError.message}
|
|
507
|
-
`);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
throw e;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
async function deleteRepositoryRest(token, owner, repo) {
|
|
514
|
-
const url = `https://api.github.com/repos/${owner}/${repo}`;
|
|
515
|
-
const res = await fetch(url, {
|
|
516
|
-
method: "DELETE",
|
|
517
|
-
headers: {
|
|
518
|
-
"Authorization": `token ${token}`,
|
|
519
|
-
"Accept": "application/vnd.github+json",
|
|
520
|
-
"User-Agent": "gh-manager-cli"
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
if (res.status === 204) return;
|
|
524
|
-
let msg = `GitHub REST delete failed (status ${res.status})`;
|
|
525
|
-
try {
|
|
526
|
-
const body = await res.json();
|
|
527
|
-
if (body && body.message) msg += `: ${body.message}`;
|
|
528
|
-
} catch {
|
|
529
|
-
}
|
|
530
|
-
throw new Error(msg);
|
|
531
|
-
}
|
|
532
|
-
async function archiveRepositoryById(client, repositoryId) {
|
|
533
|
-
const mutation = (
|
|
534
|
-
/* GraphQL */
|
|
535
|
-
`
|
|
536
|
-
mutation ArchiveRepo($repositoryId: ID!) {
|
|
537
|
-
archiveRepository(input: { repositoryId: $repositoryId }) {
|
|
538
|
-
clientMutationId
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
`
|
|
542
|
-
);
|
|
543
|
-
await client(mutation, { repositoryId });
|
|
544
|
-
}
|
|
545
|
-
async function unarchiveRepositoryById(client, repositoryId) {
|
|
546
|
-
const mutation = (
|
|
547
|
-
/* GraphQL */
|
|
548
|
-
`
|
|
549
|
-
mutation UnarchiveRepo($repositoryId: ID!) {
|
|
550
|
-
unarchiveRepository(input: { repositoryId: $repositoryId }) {
|
|
551
|
-
clientMutationId
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
`
|
|
555
|
-
);
|
|
556
|
-
await client(mutation, { repositoryId });
|
|
557
|
-
}
|
|
558
|
-
async function syncForkWithUpstream(token, owner, repo, branch = "main") {
|
|
559
|
-
const url = `https://api.github.com/repos/${owner}/${repo}/merge-upstream`;
|
|
560
|
-
const res = await fetch(url, {
|
|
561
|
-
method: "POST",
|
|
562
|
-
headers: {
|
|
563
|
-
"Authorization": `token ${token}`,
|
|
564
|
-
"Accept": "application/vnd.github+json",
|
|
565
|
-
"User-Agent": "gh-manager-cli"
|
|
566
|
-
},
|
|
567
|
-
body: JSON.stringify({ branch })
|
|
568
|
-
});
|
|
569
|
-
if (res.status === 204) {
|
|
570
|
-
return { message: "Already up-to-date", merge_type: "none", base_branch: branch };
|
|
571
|
-
}
|
|
572
|
-
if (res.status === 200) {
|
|
573
|
-
const body = await res.json();
|
|
574
|
-
return body;
|
|
575
|
-
}
|
|
576
|
-
let msg = `Fork sync failed (status ${res.status})`;
|
|
577
|
-
try {
|
|
578
|
-
const body = await res.json();
|
|
579
|
-
if (body && body.message) {
|
|
580
|
-
msg += `: ${body.message}`;
|
|
581
|
-
if (res.status === 409) {
|
|
582
|
-
msg += " (conflicts detected - manual merge required)";
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
} catch {
|
|
586
|
-
}
|
|
587
|
-
throw new Error(msg);
|
|
588
|
-
}
|
|
589
|
-
async function purgeApolloCacheFiles() {
|
|
590
|
-
try {
|
|
591
|
-
const fs4 = await import("fs");
|
|
592
|
-
const path4 = await import("path");
|
|
593
|
-
const envPaths4 = (await import("env-paths")).default;
|
|
594
|
-
const p = envPaths4("gh-manager-cli").data;
|
|
595
|
-
const cacheFile = path4.join(p, "apollo-cache.json");
|
|
596
|
-
const metaFile = path4.join(p, "apollo-cache-meta.json");
|
|
597
|
-
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
598
|
-
console.log(`\u{1F5D1}\uFE0F Purging cache files from: ${p}`);
|
|
599
|
-
}
|
|
600
|
-
try {
|
|
601
|
-
fs4.unlinkSync(cacheFile);
|
|
602
|
-
} catch {
|
|
603
|
-
}
|
|
604
|
-
try {
|
|
605
|
-
fs4.unlinkSync(metaFile);
|
|
606
|
-
} catch {
|
|
607
|
-
}
|
|
608
|
-
} catch {
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
async function inspectCacheStatus() {
|
|
612
|
-
try {
|
|
613
|
-
const fs4 = await import("fs");
|
|
614
|
-
const path4 = await import("path");
|
|
615
|
-
const envPaths4 = (await import("env-paths")).default;
|
|
616
|
-
const p = envPaths4("gh-manager-cli").data;
|
|
617
|
-
const cacheFile = path4.join(p, "apollo-cache.json");
|
|
618
|
-
const metaFile = path4.join(p, "apollo-cache-meta.json");
|
|
619
|
-
process.stderr.write(`
|
|
620
|
-
\u{1F4C2} Cache directory: ${p}
|
|
621
|
-
`);
|
|
622
|
-
try {
|
|
623
|
-
const cacheStats = fs4.statSync(cacheFile);
|
|
624
|
-
process.stderr.write(`\u{1F4BE} Cache file: ${Math.round(cacheStats.size / 1024)}KB (${cacheStats.mtime.toISOString()})
|
|
625
|
-
`);
|
|
626
|
-
} catch {
|
|
627
|
-
process.stderr.write(`\u{1F4BE} Cache file: NOT FOUND
|
|
628
|
-
`);
|
|
629
|
-
}
|
|
630
|
-
try {
|
|
631
|
-
const metaStats = fs4.statSync(metaFile);
|
|
632
|
-
const metaContent = fs4.readFileSync(metaFile, "utf8");
|
|
633
|
-
const meta = JSON.parse(metaContent);
|
|
634
|
-
process.stderr.write(`\u{1F4CA} Meta file: ${Object.keys(meta.fetched || {}).length} entries (${metaStats.mtime.toISOString()})
|
|
635
|
-
`);
|
|
636
|
-
const entries = Object.entries(meta.fetched || {});
|
|
637
|
-
if (entries.length > 0) {
|
|
638
|
-
process.stderr.write("\u{1F4CB} Recent cache entries:\n");
|
|
639
|
-
entries.slice(-3).forEach(([key, timestamp]) => {
|
|
640
|
-
const age = Date.now() - Date.parse(timestamp);
|
|
641
|
-
process.stderr.write(` ${key} (${Math.round(age / 1e3)}s ago)
|
|
642
|
-
`);
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
} catch {
|
|
646
|
-
process.stderr.write(`\u{1F4CA} Meta file: NOT FOUND
|
|
647
|
-
`);
|
|
648
|
-
}
|
|
649
|
-
process.stderr.write("\n");
|
|
650
|
-
} catch (e) {
|
|
651
|
-
process.stderr.write(`\u274C Cache inspection failed: ${e.message}
|
|
652
|
-
`);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
199
|
// src/ui/RepoList.tsx
|
|
657
|
-
import
|
|
658
|
-
import { Box, Text, useApp, useInput, useStdout } from "ink";
|
|
200
|
+
import React2, { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
|
|
201
|
+
import { Box as Box2, Text as Text2, useApp, useInput as useInput2, useStdout } from "ink";
|
|
659
202
|
import TextInput from "ink-text-input";
|
|
660
|
-
import
|
|
203
|
+
import chalk2 from "chalk";
|
|
661
204
|
|
|
662
205
|
// src/apolloMeta.ts
|
|
663
|
-
import
|
|
664
|
-
import
|
|
665
|
-
import
|
|
666
|
-
var paths2 =
|
|
206
|
+
import fs2 from "fs";
|
|
207
|
+
import path2 from "path";
|
|
208
|
+
import envPaths2 from "env-paths";
|
|
209
|
+
var paths2 = envPaths2("gh-manager-cli");
|
|
667
210
|
var dataDir = paths2.data;
|
|
668
|
-
var metaPath =
|
|
211
|
+
var metaPath = path2.join(dataDir, "apollo-cache-meta.json");
|
|
669
212
|
var VERSION = 1;
|
|
670
213
|
function readMeta() {
|
|
671
214
|
try {
|
|
672
|
-
const raw =
|
|
215
|
+
const raw = fs2.readFileSync(metaPath, "utf8");
|
|
673
216
|
const parsed = JSON.parse(raw);
|
|
674
217
|
if (parsed && typeof parsed === "object" && parsed.fetched) return parsed;
|
|
675
218
|
} catch {
|
|
@@ -678,11 +221,11 @@ function readMeta() {
|
|
|
678
221
|
}
|
|
679
222
|
function writeMeta(meta) {
|
|
680
223
|
try {
|
|
681
|
-
|
|
682
|
-
|
|
224
|
+
fs2.mkdirSync(dataDir, { recursive: true });
|
|
225
|
+
fs2.writeFileSync(metaPath, JSON.stringify(meta, null, 2), "utf8");
|
|
683
226
|
if (process.platform !== "win32") {
|
|
684
227
|
try {
|
|
685
|
-
|
|
228
|
+
fs2.chmodSync(metaPath, 384);
|
|
686
229
|
} catch {
|
|
687
230
|
}
|
|
688
231
|
}
|
|
@@ -691,7 +234,9 @@ function writeMeta(meta) {
|
|
|
691
234
|
}
|
|
692
235
|
function makeApolloKey(opts) {
|
|
693
236
|
const v = opts.viewer || "unknown";
|
|
694
|
-
|
|
237
|
+
const context = opts.ownerContext || "personal";
|
|
238
|
+
const affiliations = opts.affiliations || "OWNER";
|
|
239
|
+
return `viewer:${v}|context:${context}|affiliations:${affiliations}|sort:${opts.sortKey}:${opts.sortDir}|ps:${opts.pageSize}|forks:${opts.forkTracking ? "1" : "0"}`;
|
|
695
240
|
}
|
|
696
241
|
function makeSearchKey(opts) {
|
|
697
242
|
const v = opts.viewer || "unknown";
|
|
@@ -714,18 +259,89 @@ function markFetched(key) {
|
|
|
714
259
|
|
|
715
260
|
// src/ui/RepoList.tsx
|
|
716
261
|
import { exec } from "child_process";
|
|
717
|
-
|
|
262
|
+
|
|
263
|
+
// src/ui/OrgSwitcher.tsx
|
|
264
|
+
import { useEffect, useState } from "react";
|
|
265
|
+
import { Box, Text, useInput } from "ink";
|
|
266
|
+
import chalk from "chalk";
|
|
267
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
268
|
+
function OrgSwitcher({ token, currentContext, onSelect, onClose }) {
|
|
269
|
+
const [organizations, setOrganizations] = useState([]);
|
|
270
|
+
const [loading, setLoading] = useState(true);
|
|
271
|
+
const [error, setError] = useState(null);
|
|
272
|
+
const [cursor, setCursor] = useState(0);
|
|
273
|
+
const isPersonalContext = currentContext === "personal";
|
|
274
|
+
useEffect(() => {
|
|
275
|
+
const loadOrgs = async () => {
|
|
276
|
+
try {
|
|
277
|
+
setLoading(true);
|
|
278
|
+
const client = await import("./github-TWXF5AWM.js").then((m) => m.makeClient(token));
|
|
279
|
+
const orgs = await fetchViewerOrganizations(client);
|
|
280
|
+
setOrganizations(orgs);
|
|
281
|
+
if (!isPersonalContext) {
|
|
282
|
+
const orgLogin2 = currentContext.login;
|
|
283
|
+
const index = orgs.findIndex((org) => org.login === orgLogin2);
|
|
284
|
+
if (index !== -1) {
|
|
285
|
+
setCursor(index + 1);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
} catch (e) {
|
|
289
|
+
setError(e.message || "Failed to load organizations");
|
|
290
|
+
} finally {
|
|
291
|
+
setLoading(false);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
loadOrgs();
|
|
295
|
+
}, [token, currentContext, isPersonalContext]);
|
|
296
|
+
useInput((input, key) => {
|
|
297
|
+
if (key.escape) {
|
|
298
|
+
onClose();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (key.return) {
|
|
302
|
+
if (cursor === 0) {
|
|
303
|
+
onSelect("personal");
|
|
304
|
+
} else if (cursor <= organizations.length) {
|
|
305
|
+
const org = organizations[cursor - 1];
|
|
306
|
+
onSelect({
|
|
307
|
+
type: "organization",
|
|
308
|
+
login: org.login,
|
|
309
|
+
name: org.name || void 0
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (key.upArrow) {
|
|
315
|
+
setCursor((c) => Math.max(0, c - 1));
|
|
316
|
+
} else if (key.downArrow) {
|
|
317
|
+
setCursor((c) => Math.min(organizations.length, c + 1));
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
const totalItems = organizations.length + 1;
|
|
321
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 3, paddingY: 2, width: 60, children: [
|
|
322
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Switch Account/Organization" }),
|
|
323
|
+
loading ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "Loading organizations..." }) : error ? /* @__PURE__ */ jsx(Text, { color: "red", children: error }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
324
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: cursor === 0 ? chalk.bgCyan.black(" \u2192 ") + " " + chalk.bold("Personal Account") : " " + chalk.gray("Personal Account") }) }),
|
|
325
|
+
organizations.map((org, index) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: cursor === index + 1 ? chalk.bgCyan.black(" \u2192 ") + " " + chalk.bold(org.name || org.login) + chalk.gray(` (@${org.login})`) : " " + chalk.gray(org.name || org.login) + chalk.gray(` (@${org.login})`) }) }, org.id)),
|
|
326
|
+
organizations.length === 0 && /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "No organizations found" })
|
|
327
|
+
] }),
|
|
328
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2191/\u2193 Navigate \u2022 Enter Select \u2022 Esc Cancel" }) })
|
|
329
|
+
] });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/ui/RepoList.tsx
|
|
333
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
718
334
|
var PAGE_SIZE = process.env.GH_MANAGER_DEV === "1" || process.env.NODE_ENV === "development" ? 5 : 15;
|
|
719
335
|
function SlowSpinner() {
|
|
720
336
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
721
|
-
const [frame, setFrame] =
|
|
722
|
-
|
|
337
|
+
const [frame, setFrame] = useState2(0);
|
|
338
|
+
useEffect2(() => {
|
|
723
339
|
const timer = setInterval(() => {
|
|
724
340
|
setFrame((f) => (f + 1) % frames.length);
|
|
725
341
|
}, 500);
|
|
726
342
|
return () => clearInterval(timer);
|
|
727
343
|
}, [frames.length]);
|
|
728
|
-
return /* @__PURE__ */
|
|
344
|
+
return /* @__PURE__ */ jsx2(Text2, { children: frames[frame] });
|
|
729
345
|
}
|
|
730
346
|
function truncate(str, max = 80) {
|
|
731
347
|
if (str.length <= max) return str;
|
|
@@ -750,90 +366,93 @@ function RepoRow({ repo, selected, index, maxWidth, spacingLines, dim, forkTrack
|
|
|
750
366
|
const commitsBehind = hasCommitData ? repo.parent.defaultBranchRef.target.history.totalCount - repo.defaultBranchRef.target.history.totalCount : 0;
|
|
751
367
|
const showCommitsBehind = forkTracking && hasCommitData;
|
|
752
368
|
let line1 = "";
|
|
753
|
-
const numColor = selected ?
|
|
754
|
-
const nameColor = selected ?
|
|
369
|
+
const numColor = selected ? chalk2.cyan : chalk2.gray;
|
|
370
|
+
const nameColor = selected ? chalk2.cyan.bold : chalk2.white;
|
|
755
371
|
line1 += numColor(`${String(index).padStart(3, " ")}.`);
|
|
756
372
|
line1 += nameColor(` ${repo.nameWithOwner}`);
|
|
757
|
-
if (repo.isPrivate) line1 +=
|
|
758
|
-
if (repo.isArchived) line1 += " " +
|
|
373
|
+
if (repo.isPrivate) line1 += chalk2.yellow(" Private");
|
|
374
|
+
if (repo.isArchived) line1 += " " + chalk2.bgGray.whiteBright(" Archived ") + " ";
|
|
759
375
|
if (repo.isFork && repo.parent) {
|
|
760
|
-
line1 +=
|
|
376
|
+
line1 += chalk2.blue(` Fork of ${repo.parent.nameWithOwner}`);
|
|
761
377
|
if (showCommitsBehind) {
|
|
762
378
|
if (commitsBehind > 0) {
|
|
763
|
-
line1 +=
|
|
379
|
+
line1 += chalk2.yellow(` (${commitsBehind} behind)`);
|
|
764
380
|
} else {
|
|
765
|
-
line1 +=
|
|
381
|
+
line1 += chalk2.green(` (0 behind)`);
|
|
766
382
|
}
|
|
767
383
|
}
|
|
768
384
|
}
|
|
769
385
|
let line2 = " ";
|
|
770
|
-
const metaColor = selected ?
|
|
771
|
-
if (langName) line2 +=
|
|
386
|
+
const metaColor = selected ? chalk2.white : chalk2.gray;
|
|
387
|
+
if (langName) line2 += chalk2.hex(langColor)("\u25CF ") + metaColor(`${langName} `);
|
|
772
388
|
line2 += metaColor(`\u2605 ${repo.stargazerCount} \u2442 ${repo.forkCount} Updated ${formatDate(repo.updatedAt)}`);
|
|
773
389
|
const line3 = repo.description ? ` ${truncate(repo.description, Math.max(30, maxWidth - 10))}` : null;
|
|
774
390
|
let fullText = line1 + "\n" + line2;
|
|
775
391
|
if (line3) fullText += "\n" + metaColor(line3);
|
|
776
|
-
return /* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
778
|
-
spacingLines > 0 && /* @__PURE__ */
|
|
392
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", backgroundColor: selected ? "gray" : void 0, children: [
|
|
393
|
+
/* @__PURE__ */ jsx2(Text2, { children: dim ? chalk2.dim(fullText) : fullText }),
|
|
394
|
+
spacingLines > 0 && /* @__PURE__ */ jsx2(Box2, { height: spacingLines, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) })
|
|
779
395
|
] });
|
|
780
396
|
}
|
|
781
|
-
function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
397
|
+
function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextChange }) {
|
|
782
398
|
const { exit } = useApp();
|
|
783
399
|
const { stdout } = useStdout();
|
|
784
400
|
const client = useMemo(() => makeClient(token), [token]);
|
|
785
|
-
const [debugMessages, setDebugMessages] =
|
|
401
|
+
const [debugMessages, setDebugMessages] = useState2([]);
|
|
786
402
|
const addDebugMessage = (msg) => {
|
|
787
403
|
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
788
404
|
setDebugMessages((prev) => [...prev.slice(-9), msg]);
|
|
789
405
|
}
|
|
790
406
|
};
|
|
791
|
-
|
|
407
|
+
React2.useEffect(() => {
|
|
792
408
|
addDebugMessage(`[RepoList] Component mounted`);
|
|
793
409
|
}, []);
|
|
794
410
|
const terminalWidth = stdout?.columns ?? 80;
|
|
795
411
|
const availableHeight = maxVisibleRows ?? 20;
|
|
796
|
-
const [items, setItems] =
|
|
797
|
-
const [cursor, setCursor] =
|
|
798
|
-
const [endCursor, setEndCursor] =
|
|
799
|
-
const [hasNextPage, setHasNextPage] =
|
|
800
|
-
const [totalCount, setTotalCount] =
|
|
801
|
-
const [loading, setLoading] =
|
|
802
|
-
const [sortingLoading, setSortingLoading] =
|
|
803
|
-
const [refreshing, setRefreshing] =
|
|
804
|
-
const [loadingMore, setLoadingMore] =
|
|
805
|
-
const [error, setError] =
|
|
806
|
-
const [rateLimit, setRateLimit] =
|
|
807
|
-
const [prevRateLimit, setPrevRateLimit] =
|
|
808
|
-
const [density, setDensity] =
|
|
809
|
-
const [prefsLoaded, setPrefsLoaded] =
|
|
810
|
-
const [
|
|
811
|
-
const [
|
|
812
|
-
const [
|
|
813
|
-
const [
|
|
814
|
-
const [
|
|
815
|
-
const [
|
|
816
|
-
const [
|
|
817
|
-
const [
|
|
818
|
-
const [
|
|
819
|
-
const [
|
|
820
|
-
const [
|
|
821
|
-
const [
|
|
822
|
-
const [
|
|
823
|
-
const [
|
|
824
|
-
const [
|
|
825
|
-
const [
|
|
826
|
-
const [
|
|
827
|
-
const [
|
|
828
|
-
const [
|
|
829
|
-
const [
|
|
830
|
-
const [
|
|
831
|
-
const [
|
|
832
|
-
const [
|
|
833
|
-
const [
|
|
834
|
-
const [
|
|
835
|
-
const [
|
|
836
|
-
const [
|
|
412
|
+
const [items, setItems] = useState2([]);
|
|
413
|
+
const [cursor, setCursor] = useState2(0);
|
|
414
|
+
const [endCursor, setEndCursor] = useState2(null);
|
|
415
|
+
const [hasNextPage, setHasNextPage] = useState2(false);
|
|
416
|
+
const [totalCount, setTotalCount] = useState2(0);
|
|
417
|
+
const [loading, setLoading] = useState2(true);
|
|
418
|
+
const [sortingLoading, setSortingLoading] = useState2(false);
|
|
419
|
+
const [refreshing, setRefreshing] = useState2(false);
|
|
420
|
+
const [loadingMore, setLoadingMore] = useState2(false);
|
|
421
|
+
const [error, setError] = useState2(null);
|
|
422
|
+
const [rateLimit, setRateLimit] = useState2(void 0);
|
|
423
|
+
const [prevRateLimit, setPrevRateLimit] = useState2(void 0);
|
|
424
|
+
const [density, setDensity] = useState2(2);
|
|
425
|
+
const [prefsLoaded, setPrefsLoaded] = useState2(false);
|
|
426
|
+
const [ownerContext, setOwnerContext] = useState2("personal");
|
|
427
|
+
const [ownerAffiliations, setOwnerAffiliations] = useState2(["OWNER"]);
|
|
428
|
+
const [orgSwitcherOpen, setOrgSwitcherOpen] = useState2(false);
|
|
429
|
+
const [searchItems, setSearchItems] = useState2([]);
|
|
430
|
+
const [searchEndCursor, setSearchEndCursor] = useState2(null);
|
|
431
|
+
const [searchHasNextPage, setSearchHasNextPage] = useState2(false);
|
|
432
|
+
const [searchTotalCount, setSearchTotalCount] = useState2(0);
|
|
433
|
+
const [searchLoading, setSearchLoading] = useState2(false);
|
|
434
|
+
const [deleteMode, setDeleteMode] = useState2(false);
|
|
435
|
+
const [deleteTarget, setDeleteTarget] = useState2(null);
|
|
436
|
+
const [deleteCode, setDeleteCode] = useState2("");
|
|
437
|
+
const [typedCode, setTypedCode] = useState2("");
|
|
438
|
+
const [deleting, setDeleting] = useState2(false);
|
|
439
|
+
const [deleteError, setDeleteError] = useState2(null);
|
|
440
|
+
const [deleteConfirmStage, setDeleteConfirmStage] = useState2(false);
|
|
441
|
+
const [confirmFocus, setConfirmFocus] = useState2("delete");
|
|
442
|
+
const [archiveMode, setArchiveMode] = useState2(false);
|
|
443
|
+
const [archiveTarget, setArchiveTarget] = useState2(null);
|
|
444
|
+
const [archiving, setArchiving] = useState2(false);
|
|
445
|
+
const [archiveError, setArchiveError] = useState2(null);
|
|
446
|
+
const [archiveFocus, setArchiveFocus] = useState2("confirm");
|
|
447
|
+
const [syncMode, setSyncMode] = useState2(false);
|
|
448
|
+
const [syncTarget, setSyncTarget] = useState2(null);
|
|
449
|
+
const [syncing, setSyncing] = useState2(false);
|
|
450
|
+
const [syncError, setSyncError] = useState2(null);
|
|
451
|
+
const [syncFocus, setSyncFocus] = useState2("confirm");
|
|
452
|
+
const [infoMode, setInfoMode] = useState2(false);
|
|
453
|
+
const [logoutMode, setLogoutMode] = useState2(false);
|
|
454
|
+
const [logoutFocus, setLogoutFocus] = useState2("confirm");
|
|
455
|
+
const [logoutError, setLogoutError] = useState2(null);
|
|
837
456
|
function closeArchiveModal() {
|
|
838
457
|
setArchiveMode(false);
|
|
839
458
|
setArchiveTarget(null);
|
|
@@ -848,6 +467,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
848
467
|
setSyncError(null);
|
|
849
468
|
setSyncFocus("confirm");
|
|
850
469
|
}
|
|
470
|
+
function handleOrgContextChange(newContext) {
|
|
471
|
+
setOwnerContext(newContext);
|
|
472
|
+
storeUIPrefs({ ownerContext: newContext });
|
|
473
|
+
setCursor(0);
|
|
474
|
+
setOrgSwitcherOpen(false);
|
|
475
|
+
const newAffiliations = newContext === "personal" ? ["OWNER"] : ["ORGANIZATION_MEMBER"];
|
|
476
|
+
setOwnerAffiliations(newAffiliations);
|
|
477
|
+
storeUIPrefs({ ownerAffiliations: newAffiliations });
|
|
478
|
+
if (onOrgContextChange) {
|
|
479
|
+
onOrgContextChange(newContext);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
851
482
|
function cancelDeleteModal() {
|
|
852
483
|
setDeleteMode(false);
|
|
853
484
|
setDeleteTarget(null);
|
|
@@ -877,11 +508,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
877
508
|
setDeleteError("Failed to delete repository. Ensure delete_repo scope and admin permissions.");
|
|
878
509
|
}
|
|
879
510
|
}
|
|
880
|
-
const [filter, setFilter] =
|
|
881
|
-
const [filterMode, setFilterMode] =
|
|
882
|
-
const [sortKey, setSortKey] =
|
|
883
|
-
const [sortDir, setSortDir] =
|
|
884
|
-
const [forkTracking, setForkTracking] =
|
|
511
|
+
const [filter, setFilter] = useState2("");
|
|
512
|
+
const [filterMode, setFilterMode] = useState2(false);
|
|
513
|
+
const [sortKey, setSortKey] = useState2("updated");
|
|
514
|
+
const [sortDir, setSortDir] = useState2("desc");
|
|
515
|
+
const [forkTracking, setForkTracking] = useState2(true);
|
|
885
516
|
const sortFieldMap = {
|
|
886
517
|
"updated": "UPDATED_AT",
|
|
887
518
|
"pushed": "PUSHED_AT",
|
|
@@ -901,13 +532,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
901
532
|
field: sortFieldMap[sortKey],
|
|
902
533
|
direction: sortDir.toUpperCase()
|
|
903
534
|
};
|
|
535
|
+
const orgLogin2 = ownerContext !== "personal" ? ownerContext.login : void 0;
|
|
904
536
|
const page = await fetchViewerReposPageUnified(
|
|
905
537
|
token,
|
|
906
538
|
PAGE_SIZE,
|
|
907
539
|
after ?? null,
|
|
908
540
|
orderBy,
|
|
909
541
|
overrideForkTracking ?? forkTracking,
|
|
910
|
-
policy ?? (after ? "network-only" : "cache-first")
|
|
542
|
+
policy ?? (after ? "network-only" : "cache-first"),
|
|
543
|
+
ownerAffiliations,
|
|
544
|
+
orgLogin2
|
|
911
545
|
);
|
|
912
546
|
setItems((prev) => reset || !after ? page.nodes : [...prev, ...page.nodes]);
|
|
913
547
|
setEndCursor(page.endCursor);
|
|
@@ -920,7 +554,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
920
554
|
sortKey,
|
|
921
555
|
sortDir,
|
|
922
556
|
pageSize: PAGE_SIZE,
|
|
923
|
-
forkTracking: overrideForkTracking ?? forkTracking
|
|
557
|
+
forkTracking: overrideForkTracking ?? forkTracking,
|
|
558
|
+
ownerContext: orgLogin2 ? `org:${orgLogin2}` : "personal",
|
|
559
|
+
affiliations: ownerAffiliations.join(",")
|
|
924
560
|
});
|
|
925
561
|
markFetched(key);
|
|
926
562
|
} catch {
|
|
@@ -996,7 +632,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
996
632
|
setSearchLoading(false);
|
|
997
633
|
}
|
|
998
634
|
};
|
|
999
|
-
|
|
635
|
+
useEffect2(() => {
|
|
1000
636
|
const ui = getUIPrefs();
|
|
1001
637
|
if (ui.density !== void 0) setDensity(ui.density);
|
|
1002
638
|
if (ui.sortKey && ["updated", "pushed", "name", "stars"].includes(ui.sortKey)) {
|
|
@@ -1007,35 +643,51 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1007
643
|
}
|
|
1008
644
|
if (ui.forkTracking !== void 0) setForkTracking(ui.forkTracking);
|
|
1009
645
|
else setForkTracking(true);
|
|
646
|
+
if (ui.ownerContext) {
|
|
647
|
+
setOwnerContext(ui.ownerContext);
|
|
648
|
+
if (onOrgContextChange) {
|
|
649
|
+
onOrgContextChange(ui.ownerContext);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (ui.ownerAffiliations && Array.isArray(ui.ownerAffiliations)) {
|
|
653
|
+
setOwnerAffiliations(ui.ownerAffiliations);
|
|
654
|
+
}
|
|
1010
655
|
setPrefsLoaded(true);
|
|
1011
|
-
}, []);
|
|
1012
|
-
|
|
656
|
+
}, [onOrgContextChange]);
|
|
657
|
+
useEffect2(() => {
|
|
1013
658
|
if (!prefsLoaded) return;
|
|
1014
659
|
let policy = "cache-first";
|
|
660
|
+
const orgLogin2 = ownerContext !== "personal" ? ownerContext.login : void 0;
|
|
1015
661
|
try {
|
|
1016
662
|
const key = makeApolloKey({
|
|
1017
663
|
viewer: viewerLogin || "unknown",
|
|
1018
664
|
sortKey,
|
|
1019
665
|
sortDir,
|
|
1020
666
|
pageSize: PAGE_SIZE,
|
|
1021
|
-
forkTracking
|
|
667
|
+
forkTracking,
|
|
668
|
+
ownerContext: orgLogin2 ? `org:${orgLogin2}` : "personal",
|
|
669
|
+
affiliations: ownerAffiliations.join(",")
|
|
1022
670
|
});
|
|
1023
671
|
policy = isFresh(key) ? "cache-first" : "network-only";
|
|
1024
672
|
} catch {
|
|
1025
673
|
}
|
|
674
|
+
setCursor(0);
|
|
1026
675
|
fetchPage(null, true, false, void 0, policy);
|
|
1027
|
-
}, [client, prefsLoaded]);
|
|
1028
|
-
|
|
676
|
+
}, [client, prefsLoaded, ownerContext, ownerAffiliations]);
|
|
677
|
+
useEffect2(() => {
|
|
1029
678
|
if (!searchActive) {
|
|
1030
679
|
if (items.length > 0) {
|
|
1031
680
|
let policy = "cache-first";
|
|
681
|
+
const orgLogin2 = ownerContext !== "personal" ? ownerContext.login : void 0;
|
|
1032
682
|
try {
|
|
1033
683
|
const key = makeApolloKey({
|
|
1034
684
|
viewer: viewerLogin || "unknown",
|
|
1035
685
|
sortKey,
|
|
1036
686
|
sortDir,
|
|
1037
687
|
pageSize: PAGE_SIZE,
|
|
1038
|
-
forkTracking
|
|
688
|
+
forkTracking,
|
|
689
|
+
ownerContext: orgLogin2 ? `org:${orgLogin2}` : "personal",
|
|
690
|
+
affiliations: ownerAffiliations.join(",")
|
|
1039
691
|
});
|
|
1040
692
|
policy = isFresh(key) ? "cache-first" : "network-only";
|
|
1041
693
|
} catch {
|
|
@@ -1061,7 +713,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1061
713
|
}
|
|
1062
714
|
}
|
|
1063
715
|
}, [sortKey, sortDir]);
|
|
1064
|
-
|
|
716
|
+
useEffect2(() => {
|
|
1065
717
|
if (viewerLogin && searchActive && !searchLoading && searchItems.length === 0) {
|
|
1066
718
|
let policy = "cache-first";
|
|
1067
719
|
try {
|
|
@@ -1071,7 +723,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1071
723
|
sortKey,
|
|
1072
724
|
sortDir,
|
|
1073
725
|
pageSize: PAGE_SIZE,
|
|
1074
|
-
forkTracking
|
|
726
|
+
forkTracking,
|
|
727
|
+
ownerContext: orgLogin ? `org:${orgLogin}` : "personal",
|
|
728
|
+
affiliations: ownerAffiliations.join(",")
|
|
1075
729
|
});
|
|
1076
730
|
policy = isFresh(key, 90 * 1e3) ? "cache-first" : "network-only";
|
|
1077
731
|
} catch {
|
|
@@ -1079,7 +733,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1079
733
|
fetchSearchPage(null, true, policy);
|
|
1080
734
|
}
|
|
1081
735
|
}, [viewerLogin]);
|
|
1082
|
-
|
|
736
|
+
useInput2((input, key) => {
|
|
737
|
+
if (orgSwitcherOpen) {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
1083
740
|
if (deleteMode) {
|
|
1084
741
|
if (key.escape || input && input.toUpperCase() === "C") {
|
|
1085
742
|
cancelDeleteModal();
|
|
@@ -1315,6 +972,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1315
972
|
fetchPage(null, true, true, void 0, "network-only");
|
|
1316
973
|
})();
|
|
1317
974
|
}
|
|
975
|
+
if (input && input.toUpperCase() === "W") {
|
|
976
|
+
setOrgSwitcherOpen(true);
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
1318
979
|
if (key.ctrl && (input === "a" || input === "A")) {
|
|
1319
980
|
const repo = visibleItems[cursor];
|
|
1320
981
|
if (repo) {
|
|
@@ -1364,6 +1025,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1364
1025
|
setInfoMode(true);
|
|
1365
1026
|
return;
|
|
1366
1027
|
}
|
|
1028
|
+
if (input && input.toUpperCase() === "W") {
|
|
1029
|
+
setOrgSwitcherOpen(true);
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1367
1032
|
if (input && input.toUpperCase() === "S") {
|
|
1368
1033
|
const order = ["updated", "pushed", "name", "stars"];
|
|
1369
1034
|
const idx = order.indexOf(sortKey);
|
|
@@ -1440,12 +1105,12 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1440
1105
|
}, [filtered, sortKey, sortDir]);
|
|
1441
1106
|
const searchActive = filter.trim().length >= 3;
|
|
1442
1107
|
const visibleItems = searchActive ? searchItems : filteredAndSorted;
|
|
1443
|
-
|
|
1108
|
+
useEffect2(() => {
|
|
1444
1109
|
if (searchActive) {
|
|
1445
1110
|
addDebugMessage(`[State] searchActive=${searchActive}, searchItems=${searchItems.length}, visibleItems=${visibleItems.length}, filter="${filter}"`);
|
|
1446
1111
|
}
|
|
1447
1112
|
}, [searchActive, searchItems.length, visibleItems.length, filter]);
|
|
1448
|
-
|
|
1113
|
+
useEffect2(() => {
|
|
1449
1114
|
setCursor((c) => Math.min(c, Math.max(0, (searchActive ? searchItems.length : items.length) - 1)));
|
|
1450
1115
|
}, [searchActive, searchItems.length, items.length]);
|
|
1451
1116
|
const headerHeight = 2;
|
|
@@ -1466,7 +1131,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1466
1131
|
const end = Math.min(total, start + visibleRepos + buffer);
|
|
1467
1132
|
return { start, end };
|
|
1468
1133
|
}, [visibleItems.length, cursor, listHeight, spacingLines]);
|
|
1469
|
-
|
|
1134
|
+
useEffect2(() => {
|
|
1470
1135
|
const prefetchThreshold = Math.floor(visibleItems.length * 0.8);
|
|
1471
1136
|
const nearEnd = visibleItems.length > 0 && cursor >= prefetchThreshold;
|
|
1472
1137
|
if (searchActive) {
|
|
@@ -1488,80 +1153,80 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1488
1153
|
}
|
|
1489
1154
|
const lowRate = rateLimit && rateLimit.remaining <= Math.ceil(rateLimit.limit * 0.1);
|
|
1490
1155
|
const modalOpen = deleteMode || archiveMode || syncMode || logoutMode || infoMode;
|
|
1491
|
-
const headerBar = useMemo(() => /* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
/* @__PURE__ */
|
|
1156
|
+
const headerBar = useMemo(() => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: [
|
|
1157
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", gap: 1, children: [
|
|
1158
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: modalOpen ? "gray" : void 0, dimColor: modalOpen ? true : void 0, children: " Repositories" }),
|
|
1159
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1495
1160
|
"(",
|
|
1496
1161
|
visibleItems.length,
|
|
1497
1162
|
"/",
|
|
1498
1163
|
searchActive ? searchTotalCount : totalCount,
|
|
1499
1164
|
")"
|
|
1500
1165
|
] }),
|
|
1501
|
-
(loading || searchLoading) && /* @__PURE__ */
|
|
1166
|
+
(loading || searchLoading) && /* @__PURE__ */ jsx2(Box2, { width: 2, flexShrink: 0, flexGrow: 0, marginLeft: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: /* @__PURE__ */ jsx2(SlowSpinner, {}) }) })
|
|
1502
1167
|
] }),
|
|
1503
|
-
rateLimit && /* @__PURE__ */
|
|
1168
|
+
rateLimit && /* @__PURE__ */ jsxs2(Text2, { color: lowRate ? "yellow" : "gray", children: [
|
|
1504
1169
|
"API: ",
|
|
1505
1170
|
rateLimit.remaining,
|
|
1506
1171
|
"/",
|
|
1507
1172
|
rateLimit.limit,
|
|
1508
|
-
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */
|
|
1173
|
+
prevRateLimit !== void 0 && prevRateLimit !== rateLimit.remaining && /* @__PURE__ */ jsx2(Text2, { color: rateLimit.remaining < prevRateLimit ? "red" : "green", children: ` (${rateLimit.remaining - prevRateLimit > 0 ? "+" : ""}${rateLimit.remaining - prevRateLimit})` })
|
|
1509
1174
|
] })
|
|
1510
1175
|
] }), [visibleItems.length, searchActive, searchTotalCount, totalCount, loading, searchLoading, rateLimit, lowRate, modalOpen, prevRateLimit]);
|
|
1511
1176
|
if (error) {
|
|
1512
|
-
return /* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
1177
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", alignItems: "center", justifyContent: "center", flexGrow: 1, children: [
|
|
1178
|
+
/* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
|
|
1179
|
+
/* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: "Press 'r' to retry or 'q' to quit" })
|
|
1515
1180
|
] });
|
|
1516
1181
|
}
|
|
1517
1182
|
if (loading && items.length === 0 || sortingLoading) {
|
|
1518
|
-
return /* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
/* @__PURE__ */
|
|
1521
|
-
/* @__PURE__ */
|
|
1183
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: availableHeight, children: [
|
|
1184
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "row", justifyContent: "space-between", height: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", gap: 1, children: [
|
|
1185
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: " Repositories" }),
|
|
1186
|
+
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "(Loading...)" })
|
|
1522
1187
|
] }) }),
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
1188
|
+
/* @__PURE__ */ jsx2(Box2, { borderStyle: "single", borderColor: "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: /* @__PURE__ */ jsx2(Box2, { height: contentHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "center", children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", alignItems: "center", children: [
|
|
1189
|
+
/* @__PURE__ */ jsxs2(Box2, { height: 1, flexDirection: "row", children: [
|
|
1190
|
+
/* @__PURE__ */ jsx2(Box2, { width: 2, flexShrink: 0, flexGrow: 0, children: /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: /* @__PURE__ */ jsx2(SlowSpinner, {}) }) }),
|
|
1191
|
+
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: refreshing ? "Refreshing..." : sortingLoading ? "Applying sort..." : "Loading repositories..." })
|
|
1527
1192
|
] }),
|
|
1528
|
-
/* @__PURE__ */
|
|
1193
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: refreshing ? "Fetching latest repository data" : sortingLoading ? `Sorting by ${sortKey} (${sortDir === "asc" ? "ascending" : "descending"})` : "Fetching your GitHub repositories" }) })
|
|
1529
1194
|
] }) }) }) }),
|
|
1530
|
-
/* @__PURE__ */
|
|
1195
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Please wait..." }) })
|
|
1531
1196
|
] });
|
|
1532
1197
|
}
|
|
1533
|
-
return /* @__PURE__ */
|
|
1198
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: availableHeight, children: [
|
|
1534
1199
|
headerBar,
|
|
1535
|
-
/* @__PURE__ */
|
|
1200
|
+
/* @__PURE__ */ jsx2(Box2, { borderStyle: "single", borderColor: modalOpen ? "gray" : "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: deleteMode && deleteTarget ? (
|
|
1536
1201
|
// Centered modal; hide list content while modal is open
|
|
1537
|
-
/* @__PURE__ */
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
/* @__PURE__ */
|
|
1540
|
-
/* @__PURE__ */
|
|
1202
|
+
/* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1203
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Delete Confirmation" }),
|
|
1204
|
+
/* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u26A0\uFE0F Delete repository?" }),
|
|
1205
|
+
/* @__PURE__ */ jsx2(Box2, { height: 2, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1541
1206
|
(() => {
|
|
1542
1207
|
const langName = deleteTarget.primaryLanguage?.name || "";
|
|
1543
1208
|
const langColor = deleteTarget.primaryLanguage?.color || "#666666";
|
|
1544
1209
|
let line1 = "";
|
|
1545
|
-
line1 +=
|
|
1546
|
-
if (deleteTarget.isPrivate) line1 +=
|
|
1547
|
-
if (deleteTarget.isArchived) line1 +=
|
|
1548
|
-
if (deleteTarget.isFork && deleteTarget.parent) line1 +=
|
|
1210
|
+
line1 += chalk2.white(deleteTarget.nameWithOwner);
|
|
1211
|
+
if (deleteTarget.isPrivate) line1 += chalk2.yellow(" Private");
|
|
1212
|
+
if (deleteTarget.isArchived) line1 += chalk2.gray.dim(" Archived");
|
|
1213
|
+
if (deleteTarget.isFork && deleteTarget.parent) line1 += chalk2.blue(` Fork of ${deleteTarget.parent.nameWithOwner}`);
|
|
1549
1214
|
let line2 = "";
|
|
1550
|
-
if (langName) line2 +=
|
|
1551
|
-
line2 +=
|
|
1552
|
-
return /* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
/* @__PURE__ */
|
|
1215
|
+
if (langName) line2 += chalk2.hex(langColor)("\u25CF ") + chalk2.gray(`${langName} `);
|
|
1216
|
+
line2 += chalk2.gray(`\u2605 ${deleteTarget.stargazerCount} \u2442 ${deleteTarget.forkCount} Updated ${formatDate(deleteTarget.updatedAt)}`);
|
|
1217
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1218
|
+
/* @__PURE__ */ jsx2(Text2, { children: line1 }),
|
|
1219
|
+
/* @__PURE__ */ jsx2(Text2, { children: line2 })
|
|
1555
1220
|
] });
|
|
1556
1221
|
})(),
|
|
1557
|
-
/* @__PURE__ */
|
|
1222
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
1558
1223
|
"Type ",
|
|
1559
|
-
/* @__PURE__ */
|
|
1224
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", bold: true, children: deleteCode }),
|
|
1560
1225
|
" to confirm."
|
|
1561
1226
|
] }) }),
|
|
1562
|
-
!deleteConfirmStage && /* @__PURE__ */
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
1227
|
+
!deleteConfirmStage && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
1228
|
+
/* @__PURE__ */ jsx2(Text2, { children: "Confirm code: " }),
|
|
1229
|
+
/* @__PURE__ */ jsx2(
|
|
1565
1230
|
TextInput,
|
|
1566
1231
|
{
|
|
1567
1232
|
value: typedCode,
|
|
@@ -1588,11 +1253,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1588
1253
|
}
|
|
1589
1254
|
)
|
|
1590
1255
|
] }),
|
|
1591
|
-
deleteConfirmStage && /* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
|
|
1256
|
+
deleteConfirmStage && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
1257
|
+
/* @__PURE__ */ jsx2(Text2, { color: "red", children: "This action will permanently delete the repository. This cannot be undone." }),
|
|
1258
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1259
|
+
/* @__PURE__ */ jsx2(
|
|
1260
|
+
Box2,
|
|
1596
1261
|
{
|
|
1597
1262
|
borderStyle: "round",
|
|
1598
1263
|
borderColor: "red",
|
|
@@ -1601,11 +1266,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1601
1266
|
alignItems: "center",
|
|
1602
1267
|
justifyContent: "center",
|
|
1603
1268
|
flexDirection: "column",
|
|
1604
|
-
children: /* @__PURE__ */
|
|
1269
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: confirmFocus === "delete" ? chalk2.bgRed.white.bold(" Delete ") : chalk2.red.bold("Delete") })
|
|
1605
1270
|
}
|
|
1606
1271
|
),
|
|
1607
|
-
/* @__PURE__ */
|
|
1608
|
-
|
|
1272
|
+
/* @__PURE__ */ jsx2(
|
|
1273
|
+
Box2,
|
|
1609
1274
|
{
|
|
1610
1275
|
borderStyle: "round",
|
|
1611
1276
|
borderColor: confirmFocus === "cancel" ? "white" : "gray",
|
|
@@ -1614,16 +1279,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1614
1279
|
alignItems: "center",
|
|
1615
1280
|
justifyContent: "center",
|
|
1616
1281
|
flexDirection: "column",
|
|
1617
|
-
children: /* @__PURE__ */
|
|
1282
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: confirmFocus === "cancel" ? chalk2.bgGray.white.bold(" Cancel ") : chalk2.gray.bold("Cancel") })
|
|
1618
1283
|
}
|
|
1619
1284
|
)
|
|
1620
1285
|
] }),
|
|
1621
|
-
/* @__PURE__ */
|
|
1286
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1622
1287
|
"Press Enter to ",
|
|
1623
1288
|
confirmFocus === "delete" ? "Delete" : "Cancel",
|
|
1624
1289
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1625
1290
|
] }) }),
|
|
1626
|
-
/* @__PURE__ */
|
|
1291
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(
|
|
1627
1292
|
TextInput,
|
|
1628
1293
|
{
|
|
1629
1294
|
value: "",
|
|
@@ -1637,18 +1302,18 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1637
1302
|
}
|
|
1638
1303
|
) })
|
|
1639
1304
|
] }),
|
|
1640
|
-
deleteError && /* @__PURE__ */
|
|
1641
|
-
deleting && /* @__PURE__ */
|
|
1305
|
+
deleteError && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "magenta", children: deleteError }) }),
|
|
1306
|
+
deleting && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "Deleting..." }) })
|
|
1642
1307
|
] }) })
|
|
1643
|
-
) : archiveMode && archiveTarget ? /* @__PURE__ */
|
|
1644
|
-
/* @__PURE__ */
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1647
|
-
/* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
|
|
1308
|
+
) : archiveMode && archiveTarget ? /* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: archiveTarget.isArchived ? "green" : "yellow", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1309
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: archiveTarget.isArchived ? "Unarchive Confirmation" : "Archive Confirmation" }),
|
|
1310
|
+
/* @__PURE__ */ jsx2(Text2, { color: archiveTarget.isArchived ? "green" : "yellow", children: archiveTarget.isArchived ? "\u21BA Unarchive repository?" : "\u26A0\uFE0F Archive repository?" }),
|
|
1311
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1312
|
+
/* @__PURE__ */ jsx2(Text2, { children: archiveTarget.nameWithOwner }),
|
|
1313
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { children: archiveTarget.isArchived ? "This will make the repository active again." : "This will make the repository read-only." }) }),
|
|
1314
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1315
|
+
/* @__PURE__ */ jsx2(
|
|
1316
|
+
Box2,
|
|
1652
1317
|
{
|
|
1653
1318
|
borderStyle: "round",
|
|
1654
1319
|
borderColor: archiveTarget.isArchived ? "green" : "yellow",
|
|
@@ -1657,11 +1322,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1657
1322
|
alignItems: "center",
|
|
1658
1323
|
justifyContent: "center",
|
|
1659
1324
|
flexDirection: "column",
|
|
1660
|
-
children: /* @__PURE__ */
|
|
1325
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: archiveFocus === "confirm" ? chalk2.bgGreen.white.bold(` ${archiveTarget.isArchived ? "Unarchive" : "Archive"} `) : chalk2.bold[archiveTarget.isArchived ? "green" : "yellow"](archiveTarget.isArchived ? "Unarchive" : "Archive") })
|
|
1661
1326
|
}
|
|
1662
1327
|
),
|
|
1663
|
-
/* @__PURE__ */
|
|
1664
|
-
|
|
1328
|
+
/* @__PURE__ */ jsx2(
|
|
1329
|
+
Box2,
|
|
1665
1330
|
{
|
|
1666
1331
|
borderStyle: "round",
|
|
1667
1332
|
borderColor: archiveFocus === "cancel" ? "white" : "gray",
|
|
@@ -1670,16 +1335,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1670
1335
|
alignItems: "center",
|
|
1671
1336
|
justifyContent: "center",
|
|
1672
1337
|
flexDirection: "column",
|
|
1673
|
-
children: /* @__PURE__ */
|
|
1338
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: archiveFocus === "cancel" ? chalk2.bgGray.white.bold(" Cancel ") : chalk2.gray.bold("Cancel") })
|
|
1674
1339
|
}
|
|
1675
1340
|
)
|
|
1676
1341
|
] }),
|
|
1677
|
-
/* @__PURE__ */
|
|
1342
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1678
1343
|
"Press Enter to ",
|
|
1679
1344
|
archiveFocus === "confirm" ? archiveTarget.isArchived ? "Unarchive" : "Archive" : "Cancel",
|
|
1680
1345
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1681
1346
|
] }) }),
|
|
1682
|
-
/* @__PURE__ */
|
|
1347
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(
|
|
1683
1348
|
TextInput,
|
|
1684
1349
|
{
|
|
1685
1350
|
value: "",
|
|
@@ -1707,21 +1372,21 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1707
1372
|
}
|
|
1708
1373
|
}
|
|
1709
1374
|
) }),
|
|
1710
|
-
archiveError && /* @__PURE__ */
|
|
1711
|
-
archiving && /* @__PURE__ */
|
|
1712
|
-
] }) }) : syncMode && syncTarget ? /* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
1715
|
-
/* @__PURE__ */
|
|
1716
|
-
/* @__PURE__ */
|
|
1717
|
-
syncTarget.parent && /* @__PURE__ */
|
|
1375
|
+
archiveError && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "magenta", children: archiveError }) }),
|
|
1376
|
+
archiving && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: archiveTarget.isArchived ? "Unarchiving..." : "Archiving..." }) })
|
|
1377
|
+
] }) }) : syncMode && syncTarget ? /* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1378
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Sync Fork Confirmation" }),
|
|
1379
|
+
/* @__PURE__ */ jsx2(Text2, { color: "blue", children: "\u27F2 Sync fork with upstream?" }),
|
|
1380
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1381
|
+
/* @__PURE__ */ jsx2(Text2, { children: syncTarget.nameWithOwner }),
|
|
1382
|
+
syncTarget.parent && /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1718
1383
|
"Upstream: ",
|
|
1719
1384
|
syncTarget.parent.nameWithOwner
|
|
1720
1385
|
] }),
|
|
1721
|
-
/* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
|
|
1386
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { children: "This will merge upstream changes into your fork." }) }),
|
|
1387
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1388
|
+
/* @__PURE__ */ jsx2(
|
|
1389
|
+
Box2,
|
|
1725
1390
|
{
|
|
1726
1391
|
borderStyle: "round",
|
|
1727
1392
|
borderColor: "blue",
|
|
@@ -1730,11 +1395,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1730
1395
|
alignItems: "center",
|
|
1731
1396
|
justifyContent: "center",
|
|
1732
1397
|
flexDirection: "column",
|
|
1733
|
-
children: /* @__PURE__ */
|
|
1398
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: syncFocus === "confirm" ? chalk2.bgBlue.white.bold(" Sync ") : chalk2.blue.bold("Sync") })
|
|
1734
1399
|
}
|
|
1735
1400
|
),
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
|
|
1401
|
+
/* @__PURE__ */ jsx2(
|
|
1402
|
+
Box2,
|
|
1738
1403
|
{
|
|
1739
1404
|
borderStyle: "round",
|
|
1740
1405
|
borderColor: syncFocus === "cancel" ? "white" : "gray",
|
|
@@ -1743,16 +1408,16 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1743
1408
|
alignItems: "center",
|
|
1744
1409
|
justifyContent: "center",
|
|
1745
1410
|
flexDirection: "column",
|
|
1746
|
-
children: /* @__PURE__ */
|
|
1411
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: syncFocus === "cancel" ? chalk2.bgGray.white.bold(" Cancel ") : chalk2.gray.bold("Cancel") })
|
|
1747
1412
|
}
|
|
1748
1413
|
)
|
|
1749
1414
|
] }),
|
|
1750
|
-
/* @__PURE__ */
|
|
1415
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1751
1416
|
"Press Enter to ",
|
|
1752
1417
|
syncFocus === "confirm" ? "Sync" : "Cancel",
|
|
1753
1418
|
" \u2022 y to confirm \u2022 c to cancel"
|
|
1754
1419
|
] }) }),
|
|
1755
|
-
/* @__PURE__ */
|
|
1420
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(
|
|
1756
1421
|
TextInput,
|
|
1757
1422
|
{
|
|
1758
1423
|
value: "",
|
|
@@ -1794,14 +1459,14 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1794
1459
|
}
|
|
1795
1460
|
}
|
|
1796
1461
|
) }),
|
|
1797
|
-
syncError && /* @__PURE__ */
|
|
1798
|
-
syncing && /* @__PURE__ */
|
|
1799
|
-
] }) }) : logoutMode ? /* @__PURE__ */
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
1803
|
-
/* @__PURE__ */
|
|
1804
|
-
|
|
1462
|
+
syncError && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "magenta", children: syncError }) }),
|
|
1463
|
+
syncing && /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "Syncing..." }) })
|
|
1464
|
+
] }) }) : logoutMode ? /* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 80), children: [
|
|
1465
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Logout Confirmation" }),
|
|
1466
|
+
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "Are you sure you want to log out?" }),
|
|
1467
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", gap: 6, children: [
|
|
1468
|
+
/* @__PURE__ */ jsx2(
|
|
1469
|
+
Box2,
|
|
1805
1470
|
{
|
|
1806
1471
|
borderStyle: "round",
|
|
1807
1472
|
borderColor: "cyan",
|
|
@@ -1810,11 +1475,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1810
1475
|
alignItems: "center",
|
|
1811
1476
|
justifyContent: "center",
|
|
1812
1477
|
flexDirection: "column",
|
|
1813
|
-
children: /* @__PURE__ */
|
|
1478
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: logoutFocus === "confirm" ? chalk2.bgCyan.white.bold(" Logout ") : chalk2.cyan.bold("Logout") })
|
|
1814
1479
|
}
|
|
1815
1480
|
),
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
|
|
1481
|
+
/* @__PURE__ */ jsx2(
|
|
1482
|
+
Box2,
|
|
1818
1483
|
{
|
|
1819
1484
|
borderStyle: "round",
|
|
1820
1485
|
borderColor: logoutFocus === "cancel" ? "white" : "gray",
|
|
@@ -1823,82 +1488,91 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1823
1488
|
alignItems: "center",
|
|
1824
1489
|
justifyContent: "center",
|
|
1825
1490
|
flexDirection: "column",
|
|
1826
|
-
children: /* @__PURE__ */
|
|
1491
|
+
children: /* @__PURE__ */ jsx2(Text2, { children: logoutFocus === "cancel" ? chalk2.bgGray.white.bold(" Cancel ") : chalk2.gray.bold("Cancel") })
|
|
1827
1492
|
}
|
|
1828
1493
|
)
|
|
1829
1494
|
] }),
|
|
1830
|
-
/* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1831
1496
|
"Press Enter to ",
|
|
1832
1497
|
logoutFocus === "confirm" ? "Logout" : "Cancel",
|
|
1833
1498
|
" \u2022 Y to confirm \u2022 C to cancel"
|
|
1834
1499
|
] }) })
|
|
1835
|
-
] }) }) :
|
|
1500
|
+
] }) }) : orgSwitcherOpen ? /* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsx2(
|
|
1501
|
+
OrgSwitcher,
|
|
1502
|
+
{
|
|
1503
|
+
token,
|
|
1504
|
+
currentContext: ownerContext,
|
|
1505
|
+
onSelect: handleOrgContextChange,
|
|
1506
|
+
onClose: () => setOrgSwitcherOpen(false)
|
|
1507
|
+
}
|
|
1508
|
+
) }) : infoMode ? /* @__PURE__ */ jsx2(Box2, { height: contentHeight, alignItems: "center", justifyContent: "center", children: (() => {
|
|
1836
1509
|
const repo = visibleItems[cursor];
|
|
1837
|
-
if (!repo) return /* @__PURE__ */
|
|
1510
|
+
if (!repo) return /* @__PURE__ */ jsx2(Text2, { color: "red", children: "No repository selected." });
|
|
1838
1511
|
const langName = repo.primaryLanguage?.name || "N/A";
|
|
1839
1512
|
const langColor = repo.primaryLanguage?.color || "#666666";
|
|
1840
|
-
return /* @__PURE__ */
|
|
1841
|
-
/* @__PURE__ */
|
|
1842
|
-
/* @__PURE__ */
|
|
1843
|
-
/* @__PURE__ */
|
|
1844
|
-
repo.description && /* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
1847
|
-
repo.isPrivate ?
|
|
1848
|
-
repo.isArchived ?
|
|
1849
|
-
repo.isFork ?
|
|
1513
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 3, paddingY: 2, width: Math.min(terminalWidth - 8, 90), children: [
|
|
1514
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Repository Info" }),
|
|
1515
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1516
|
+
/* @__PURE__ */ jsx2(Text2, { children: chalk2.bold(repo.nameWithOwner) }),
|
|
1517
|
+
repo.description && /* @__PURE__ */ jsx2(Text2, { color: "gray", children: repo.description }),
|
|
1518
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1519
|
+
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
1520
|
+
repo.isPrivate ? chalk2.yellow("Private") : chalk2.green("Public"),
|
|
1521
|
+
repo.isArchived ? chalk2.gray(" Archived") : "",
|
|
1522
|
+
repo.isFork ? chalk2.blue(" Fork") : ""
|
|
1850
1523
|
] }),
|
|
1851
|
-
/* @__PURE__ */
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
|
|
1854
|
-
|
|
1524
|
+
/* @__PURE__ */ jsx2(Text2, { children: chalk2.gray(`\u2605 ${repo.stargazerCount} \u2442 ${repo.forkCount}`) }),
|
|
1525
|
+
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
1526
|
+
chalk2.hex(langColor)(`\u25CF `),
|
|
1527
|
+
chalk2.gray(`${langName}`)
|
|
1855
1528
|
] }),
|
|
1856
|
-
/* @__PURE__ */
|
|
1529
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1857
1530
|
"Updated: ",
|
|
1858
1531
|
formatDate(repo.updatedAt),
|
|
1859
1532
|
" \u2022 Pushed: ",
|
|
1860
1533
|
formatDate(repo.pushedAt)
|
|
1861
1534
|
] }),
|
|
1862
|
-
/* @__PURE__ */
|
|
1535
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
1863
1536
|
"Size: ",
|
|
1864
1537
|
repo.diskUsage,
|
|
1865
1538
|
" KB"
|
|
1866
1539
|
] }),
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1540
|
+
/* @__PURE__ */ jsx2(Box2, { height: 1, children: /* @__PURE__ */ jsx2(Text2, { children: " " }) }),
|
|
1541
|
+
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Press Esc or I to close" })
|
|
1869
1542
|
] });
|
|
1870
|
-
})() }) : /* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
1872
|
-
/* @__PURE__ */
|
|
1543
|
+
})() }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1544
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", gap: 2, marginBottom: 1, children: [
|
|
1545
|
+
/* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: ownerContext === "personal" ? "Personal Account" : `Organization: ${ownerContext.name || ownerContext.login}` }),
|
|
1546
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "gray", dimColor: true, children: [
|
|
1873
1547
|
"Sort: ",
|
|
1874
1548
|
sortKey,
|
|
1875
1549
|
" ",
|
|
1876
1550
|
sortDir === "asc" ? "\u2191" : "\u2193"
|
|
1877
1551
|
] }),
|
|
1878
|
-
/* @__PURE__ */
|
|
1552
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "gray", dimColor: true, children: [
|
|
1879
1553
|
"Forks - Commits Behind: ",
|
|
1880
1554
|
forkTracking ? "ON" : "OFF"
|
|
1881
1555
|
] }),
|
|
1882
|
-
filter && !searchActive && /* @__PURE__ */
|
|
1556
|
+
filter && !searchActive && /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
|
|
1883
1557
|
'Filter: "',
|
|
1884
1558
|
filter,
|
|
1885
1559
|
'"'
|
|
1886
1560
|
] }),
|
|
1887
|
-
searchActive && /* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1561
|
+
searchActive && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1562
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
|
|
1889
1563
|
'Search: "',
|
|
1890
1564
|
filter.trim(),
|
|
1891
1565
|
'"'
|
|
1892
1566
|
] }),
|
|
1893
|
-
searchLoading && /* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1567
|
+
searchLoading && /* @__PURE__ */ jsx2(Box2, { marginLeft: 1, children: /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
|
|
1568
|
+
/* @__PURE__ */ jsx2(SlowSpinner, {}),
|
|
1895
1569
|
" Searching\u2026"
|
|
1896
1570
|
] }) })
|
|
1897
1571
|
] })
|
|
1898
1572
|
] }),
|
|
1899
|
-
filterMode && /* @__PURE__ */
|
|
1900
|
-
/* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
1573
|
+
filterMode && /* @__PURE__ */ jsxs2(Box2, { marginBottom: 1, children: [
|
|
1574
|
+
/* @__PURE__ */ jsx2(Text2, { children: "Filter: " }),
|
|
1575
|
+
/* @__PURE__ */ jsx2(
|
|
1902
1576
|
TextInput,
|
|
1903
1577
|
{
|
|
1904
1578
|
value: filter,
|
|
@@ -1938,10 +1612,10 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1938
1612
|
}
|
|
1939
1613
|
)
|
|
1940
1614
|
] }),
|
|
1941
|
-
/* @__PURE__ */
|
|
1942
|
-
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */
|
|
1615
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: listHeight, children: [
|
|
1616
|
+
filterMode && filter.trim().length > 0 && filter.trim().length < 3 ? /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: "Type at least 3 characters to search" }) }) : visibleItems.slice(windowed.start, windowed.end).map((repo, i) => {
|
|
1943
1617
|
const idx = windowed.start + i;
|
|
1944
|
-
return /* @__PURE__ */
|
|
1618
|
+
return /* @__PURE__ */ jsx2(
|
|
1945
1619
|
RepoRow,
|
|
1946
1620
|
{
|
|
1947
1621
|
repo,
|
|
@@ -1954,42 +1628,43 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin }) {
|
|
|
1954
1628
|
repo.nameWithOwner
|
|
1955
1629
|
);
|
|
1956
1630
|
}),
|
|
1957
|
-
loadingMore && hasNextPage && /* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
1631
|
+
loadingMore && hasNextPage && /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", children: [
|
|
1632
|
+
/* @__PURE__ */ jsx2(Box2, { width: 2, flexShrink: 0, flexGrow: 0, marginRight: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: /* @__PURE__ */ jsx2(SlowSpinner, {}) }) }),
|
|
1633
|
+
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "Loading more repositories..." })
|
|
1960
1634
|
] }) }),
|
|
1961
|
-
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */
|
|
1635
|
+
!loading && !searchLoading && visibleItems.length === 0 && /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", alignItems: "center", flexGrow: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: searchActive ? "No repositories match your search" : filter ? "No repositories match your filter" : "No repositories found" }) })
|
|
1962
1636
|
] })
|
|
1963
1637
|
] }) }),
|
|
1964
|
-
/* @__PURE__ */
|
|
1965
|
-
/* @__PURE__ */
|
|
1966
|
-
/* @__PURE__ */
|
|
1638
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
1639
|
+
/* @__PURE__ */ jsx2(Box2, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: modalOpen ? true : void 0, children: "\u2191\u2193 Navigate \u2022 Ctrl+G Top \u2022 G Bottom \u2022 / Filter \u2022 W Org Switcher \u2022 S Sort \u2022 D Direction \u2022 T Density \u2022 F Forks \u2022 \u23CE/O Open" }) }),
|
|
1640
|
+
/* @__PURE__ */ jsx2(Box2, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: modalOpen ? true : void 0, children: "Del/Ctrl+Backspace Delete \u2022 Ctrl+A Un/Archive \u2022 Ctrl+U Sync Fork \u2022 I Info \u2022 Ctrl+I Cache \u2022 Ctrl+L Logout \u2022 R Refresh \u2022 Q Quit" }) })
|
|
1967
1641
|
] }),
|
|
1968
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
debugMessages.length === 0 ? /* @__PURE__ */
|
|
1642
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [
|
|
1643
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "yellow", children: "Debug Messages:" }),
|
|
1644
|
+
debugMessages.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No debug messages yet..." }) : debugMessages.map((msg, i) => /* @__PURE__ */ jsx2(Text2, { color: "gray", children: msg }, i))
|
|
1971
1645
|
] })
|
|
1972
1646
|
] });
|
|
1973
1647
|
}
|
|
1974
1648
|
|
|
1975
1649
|
// src/ui/App.tsx
|
|
1976
|
-
import { jsx as
|
|
1650
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1977
1651
|
var packageJson = require_package();
|
|
1978
1652
|
function App() {
|
|
1979
1653
|
const { exit } = useApp2();
|
|
1980
1654
|
const { stdout } = useStdout2();
|
|
1981
|
-
const [mode, setMode] =
|
|
1982
|
-
const [token, setToken] =
|
|
1983
|
-
const [input, setInput] =
|
|
1984
|
-
const [error, setError] =
|
|
1985
|
-
const [viewer, setViewer] =
|
|
1986
|
-
const [rateLimitReset, setRateLimitReset] =
|
|
1987
|
-
const [
|
|
1655
|
+
const [mode, setMode] = useState3("checking");
|
|
1656
|
+
const [token, setToken] = useState3(null);
|
|
1657
|
+
const [input, setInput] = useState3("");
|
|
1658
|
+
const [error, setError] = useState3(null);
|
|
1659
|
+
const [viewer, setViewer] = useState3(null);
|
|
1660
|
+
const [rateLimitReset, setRateLimitReset] = useState3(null);
|
|
1661
|
+
const [orgContext, setOrgContext] = useState3("personal");
|
|
1662
|
+
const [dims, setDims] = useState3(() => {
|
|
1988
1663
|
const cols = stdout?.columns ?? 100;
|
|
1989
1664
|
const rows = stdout?.rows ?? 30;
|
|
1990
1665
|
return { cols, rows };
|
|
1991
1666
|
});
|
|
1992
|
-
|
|
1667
|
+
useEffect3(() => {
|
|
1993
1668
|
if (!stdout) return;
|
|
1994
1669
|
const onResize = () => {
|
|
1995
1670
|
const cols = stdout.columns ?? 100;
|
|
@@ -2001,7 +1676,7 @@ function App() {
|
|
|
2001
1676
|
stdout.off?.("resize", onResize);
|
|
2002
1677
|
};
|
|
2003
1678
|
}, [stdout]);
|
|
2004
|
-
|
|
1679
|
+
useEffect3(() => {
|
|
2005
1680
|
const env = getTokenFromEnv();
|
|
2006
1681
|
const stored = getStoredToken();
|
|
2007
1682
|
if (env) {
|
|
@@ -2014,7 +1689,7 @@ function App() {
|
|
|
2014
1689
|
setMode("prompt");
|
|
2015
1690
|
}
|
|
2016
1691
|
}, []);
|
|
2017
|
-
|
|
1692
|
+
useEffect3(() => {
|
|
2018
1693
|
(async () => {
|
|
2019
1694
|
if (mode !== "validating" || !token) return;
|
|
2020
1695
|
const timeoutId = setTimeout(() => {
|
|
@@ -2099,7 +1774,7 @@ function App() {
|
|
|
2099
1774
|
setViewer(null);
|
|
2100
1775
|
setMode("prompt");
|
|
2101
1776
|
};
|
|
2102
|
-
|
|
1777
|
+
useInput3((input2, key) => {
|
|
2103
1778
|
if (mode === "prompt" && key.escape) {
|
|
2104
1779
|
exit();
|
|
2105
1780
|
}
|
|
@@ -2125,24 +1800,20 @@ function App() {
|
|
|
2125
1800
|
}
|
|
2126
1801
|
});
|
|
2127
1802
|
const verticalPadding = Math.floor(dims.rows * 0.15);
|
|
2128
|
-
const header = useMemo2(() => /* @__PURE__ */
|
|
2129
|
-
/* @__PURE__ */
|
|
2130
|
-
/* @__PURE__ */
|
|
1803
|
+
const header = useMemo2(() => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [
|
|
1804
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", gap: 1, children: [
|
|
1805
|
+
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "cyan", children: [
|
|
2131
1806
|
" ",
|
|
2132
1807
|
"GitHub Repository Manager"
|
|
2133
1808
|
] }),
|
|
2134
|
-
/* @__PURE__ */
|
|
1809
|
+
/* @__PURE__ */ jsxs3(Text3, { color: "gray", dimColor: true, children: [
|
|
2135
1810
|
"v",
|
|
2136
1811
|
packageJson.version
|
|
2137
1812
|
] }),
|
|
2138
|
-
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */
|
|
1813
|
+
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsx3(Text3, { backgroundColor: "blue", color: "white", children: " debug mode " })
|
|
2139
1814
|
] }),
|
|
2140
|
-
viewer && /* @__PURE__ */
|
|
2141
|
-
|
|
2142
|
-
viewer,
|
|
2143
|
-
" "
|
|
2144
|
-
] })
|
|
2145
|
-
] }), [viewer]);
|
|
1815
|
+
viewer && /* @__PURE__ */ jsx3(Text3, { color: "gray", children: orgContext !== "personal" && orgContext.login ? `${orgContext.login}/@${viewer} ` : `@${viewer} ` })
|
|
1816
|
+
] }), [viewer, orgContext]);
|
|
2146
1817
|
if (mode === "rate_limited") {
|
|
2147
1818
|
const formatResetTime = (resetTime) => {
|
|
2148
1819
|
if (!resetTime) return "Unknown";
|
|
@@ -2164,55 +1835,55 @@ function App() {
|
|
|
2164
1835
|
return "Unknown";
|
|
2165
1836
|
}
|
|
2166
1837
|
};
|
|
2167
|
-
return /* @__PURE__ */
|
|
1838
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
2168
1839
|
header,
|
|
2169
|
-
/* @__PURE__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
2171
|
-
/* @__PURE__ */
|
|
2172
|
-
/* @__PURE__ */
|
|
2173
|
-
rateLimitReset && /* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2175
|
-
/* @__PURE__ */
|
|
1840
|
+
/* @__PURE__ */ jsx3(Box3, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs3(Box3, { borderStyle: "single", borderColor: "yellow", paddingX: 3, paddingY: 2, flexDirection: "column", width: Math.min(dims.cols - 8, 80), children: [
|
|
1841
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "yellow", marginBottom: 1, children: "\u26A0\uFE0F Rate Limit Exceeded" }),
|
|
1842
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", marginBottom: 1, children: "You've hit GitHub's API rate limit for your token." }),
|
|
1843
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", marginBottom: 1, children: "This happens when you make too many requests in a short time." }),
|
|
1844
|
+
rateLimitReset && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, marginBottom: 1, children: [
|
|
1845
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1846
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "Reset in:" }),
|
|
2176
1847
|
" ",
|
|
2177
|
-
/* @__PURE__ */
|
|
1848
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: formatResetTime(rateLimitReset) })
|
|
2178
1849
|
] }),
|
|
2179
|
-
/* @__PURE__ */
|
|
1850
|
+
/* @__PURE__ */ jsxs3(Text3, { color: "gray", dimColor: true, children: [
|
|
2180
1851
|
"(",
|
|
2181
1852
|
new Date(rateLimitReset).toLocaleTimeString(),
|
|
2182
1853
|
")"
|
|
2183
1854
|
] })
|
|
2184
1855
|
] }),
|
|
2185
|
-
/* @__PURE__ */
|
|
2186
|
-
/* @__PURE__ */
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
1856
|
+
/* @__PURE__ */ jsxs3(Box3, { marginTop: 2, flexDirection: "column", gap: 1, children: [
|
|
1857
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: "What would you like to do?" }),
|
|
1858
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingLeft: 2, children: [
|
|
1859
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1860
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "r" }),
|
|
2190
1861
|
" - Retry now ",
|
|
2191
1862
|
rateLimitReset && formatResetTime(rateLimitReset) !== "Now (should be reset)" ? "(likely to fail until reset)" : "(should work now)"
|
|
2192
1863
|
] }),
|
|
2193
|
-
/* @__PURE__ */
|
|
2194
|
-
/* @__PURE__ */
|
|
1864
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1865
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "l" }),
|
|
2195
1866
|
" - Logout and use a different token"
|
|
2196
1867
|
] }),
|
|
2197
|
-
/* @__PURE__ */
|
|
2198
|
-
/* @__PURE__ */
|
|
1868
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1869
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", bold: true, children: "q/Esc" }),
|
|
2199
1870
|
" - Quit application"
|
|
2200
1871
|
] })
|
|
2201
1872
|
] })
|
|
2202
1873
|
] }),
|
|
2203
|
-
/* @__PURE__ */
|
|
1874
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, marginTop: 2, children: "Tip: Using multiple tokens or waiting between requests can help avoid rate limits." })
|
|
2204
1875
|
] }) })
|
|
2205
1876
|
] });
|
|
2206
1877
|
}
|
|
2207
1878
|
if (mode === "prompt") {
|
|
2208
|
-
return /* @__PURE__ */
|
|
1879
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
2209
1880
|
header,
|
|
2210
|
-
/* @__PURE__ */
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
/* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2214
|
-
/* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
1881
|
+
/* @__PURE__ */ jsx3(Box3, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs3(Box3, { borderStyle: "single", borderColor: "cyan", paddingX: 2, paddingY: 1, flexDirection: "column", children: [
|
|
1882
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, marginBottom: 1, children: "Authentication Required" }),
|
|
1883
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", marginBottom: 1, children: "Enter your GitHub Personal Access Token" }),
|
|
1884
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
1885
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Token: " }),
|
|
1886
|
+
/* @__PURE__ */ jsx3(
|
|
2216
1887
|
TextInput2,
|
|
2217
1888
|
{
|
|
2218
1889
|
value: input,
|
|
@@ -2222,43 +1893,44 @@ function App() {
|
|
|
2222
1893
|
}
|
|
2223
1894
|
)
|
|
2224
1895
|
] }),
|
|
2225
|
-
error && /* @__PURE__ */
|
|
2226
|
-
/* @__PURE__ */
|
|
2227
|
-
/* @__PURE__ */
|
|
1896
|
+
error && /* @__PURE__ */ jsx3(Text3, { color: "red", marginTop: 1, children: error }),
|
|
1897
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, marginTop: 1, children: "The token will be stored securely in your local config" }),
|
|
1898
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to quit" })
|
|
2228
1899
|
] }) })
|
|
2229
1900
|
] });
|
|
2230
1901
|
}
|
|
2231
1902
|
if (mode === "validating" || mode === "checking") {
|
|
2232
|
-
return /* @__PURE__ */
|
|
1903
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
2233
1904
|
header,
|
|
2234
|
-
/* @__PURE__ */
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
mode === "validating" && /* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ jsx3(Box3, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", alignItems: "center", children: [
|
|
1906
|
+
/* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "Validating token..." }),
|
|
1907
|
+
mode === "validating" && /* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, marginTop: 1, children: "Press Esc to cancel" })
|
|
2237
1908
|
] }) })
|
|
2238
1909
|
] });
|
|
2239
1910
|
}
|
|
2240
1911
|
if (mode === "error") {
|
|
2241
|
-
return /* @__PURE__ */
|
|
1912
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
2242
1913
|
header,
|
|
2243
|
-
/* @__PURE__ */
|
|
1914
|
+
/* @__PURE__ */ jsx3(Box3, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx3(Text3, { color: "red", children: error ?? "Unexpected error" }) })
|
|
2244
1915
|
] });
|
|
2245
1916
|
}
|
|
2246
|
-
return /* @__PURE__ */
|
|
1917
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", height: dims.rows, paddingX: 2, paddingTop: verticalPadding, paddingBottom: verticalPadding, children: [
|
|
2247
1918
|
header,
|
|
2248
|
-
/* @__PURE__ */
|
|
1919
|
+
/* @__PURE__ */ jsx3(
|
|
2249
1920
|
RepoList,
|
|
2250
1921
|
{
|
|
2251
1922
|
token,
|
|
2252
1923
|
maxVisibleRows: dims.rows - verticalPadding * 2 - 4,
|
|
2253
1924
|
onLogout: handleLogout,
|
|
2254
|
-
viewerLogin: viewer ?? void 0
|
|
1925
|
+
viewerLogin: viewer ?? void 0,
|
|
1926
|
+
onOrgContextChange: setOrgContext
|
|
2255
1927
|
}
|
|
2256
1928
|
)
|
|
2257
1929
|
] });
|
|
2258
1930
|
}
|
|
2259
1931
|
|
|
2260
1932
|
// src/index.tsx
|
|
2261
|
-
import { jsx as
|
|
1933
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2262
1934
|
if (process.env.GH_MANAGER_DEBUG === "1") {
|
|
2263
1935
|
process.stderr.write("\u{1F41B} Debug mode enabled\n");
|
|
2264
1936
|
}
|
|
@@ -2271,8 +1943,8 @@ process.on("unhandledRejection", (reason) => {
|
|
|
2271
1943
|
process.exit(1);
|
|
2272
1944
|
});
|
|
2273
1945
|
render(
|
|
2274
|
-
/* @__PURE__ */
|
|
2275
|
-
/* @__PURE__ */
|
|
2276
|
-
/* @__PURE__ */
|
|
1946
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1947
|
+
/* @__PURE__ */ jsx4(App, {}),
|
|
1948
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray" })
|
|
2277
1949
|
] })
|
|
2278
1950
|
);
|