History

feat(prs): navigate, merge and rebase GitHub stacks (#10875)

Julius Marminge committed 2 months ago

Commit de379641 parent f0401c653 files · +3104 −464Browse files

Showing the changes to apps/web/src/components/pullRequest/pullRequestStackSnapshot.ts (1 of 53 files). Show all

Unified · Split

apps/web/src/components/pullRequest/pullRequestStackSnapshot.ts+73−0
@@ -0,0 +1,73 @@
1import type { PullRequestRef, PullRequestStack, ThreadPullRequestLink } from "@t3tools/contracts";
2
3/** Saved native membership is enough for navigation, but never supplies action head SHAs. */
4export function savedPullRequestStack(
5 links: ReadonlyArray<ThreadPullRequestLink>,
6 reference: PullRequestRef,
7): PullRequestStack | null {
8 const host = reference.host?.toLowerCase();
9 if (!host) return null;
10 const matching = links.filter(
11 (link) =>
12 link.host.toLowerCase() === host &&
13 link.repository.toLowerCase() === reference.repository.toLowerCase(),
14 );
15 const exact = matching.filter((link) => link.number === reference.number);
16 const candidates =
17 exact.length > 0
18 ? exact
19 : matching.filter((link) =>
20 link.stack?.layers.some((layer) => layer.number === reference.number),
21 );
22 const newest = candidates.toSorted(
23 (a, b) =>
24 Date.parse(b.snapshot?.syncedAt ?? b.linkedAt) -
25 Date.parse(a.snapshot?.syncedAt ?? a.linkedAt),
26 )[0];
27 const stack = newest?.stack;
28 if (!stack || !stack.layers.some((layer) => layer.number === reference.number)) return null;
29 return {
30 id: stack.id,
31 number: stack.number,
32 url: stack.url,
33 base: stack.base,
34 layers: stack.layers.map((layer) => {
35 const snapshot = matching
36 .filter((link) => link.number === layer.number)
37 .toSorted(
38 (a, b) =>
39 Date.parse(b.snapshot?.syncedAt ?? b.linkedAt) -
40 Date.parse(a.snapshot?.syncedAt ?? a.linkedAt),
41 )[0]?.snapshot;
42 return {
43 ...layer,
44 ...(snapshot ? { title: snapshot.title, isDraft: snapshot.isDraft } : {}),
45 };
46 }),
47 };
48}
49
50/** A fresh absence overrides saved membership; failed refreshes preserve available navigation. */
51export function pullRequestStackView(
52 query: {
53 data: PullRequestStack | null;
54 isSuccess: boolean;
55 isPending: boolean;
56 error: string | null;
57 },
58 saved: PullRequestStack | null,
59) {
60 const data = query.isSuccess ? query.data : (query.data ?? saved);
61 return {
62 data,
63 isFresh: query.isSuccess && !query.isPending,
64 notice:
65 data === null
66 ? null
67 : query.error
68 ? "Stack data may be stale. We couldn’t refresh it."
69 : !query.isSuccess || query.isPending
70 ? "Refreshing stack… Showing saved data."
71 : null,
72 };
73}