(currentVersion: string | undefined)
| 67 | } |
| 68 | |
| 69 | function useLatestVersion(currentVersion: string | undefined) { |
| 70 | // The channel shown in the upgrade command differs from the channel |
| 71 | // fetched for comparison: the command always names a real channel, while |
| 72 | // the fetch is skipped entirely for a version with nothing to compare. |
| 73 | const displayChannel: UpdateChannel = currentVersion |
| 74 | ? resolveUpdateChannel(currentVersion) |
| 75 | : "latest"; |
| 76 | const fetchChannel = updateFetchChannel(currentVersion); |
| 77 | const [latestVersion, setLatestVersion] = useState<string | null>(null); |
| 78 | |
| 79 | useEffect(() => { |
| 80 | if (fetchChannel === null) return; |
| 81 | let cancelled = false; |
| 82 | void Effect.runPromiseExit( |
| 83 | Effect.tryPromise({ |
| 84 | try: async () => { |
| 85 | const res = await fetch(EXECUTOR_DIST_TAGS_PATH); |
| 86 | if (!res.ok) return null; |
| 87 | return (await res.json()) as Partial<Record<UpdateChannel, string>>; |
| 88 | }, |
| 89 | catch: (cause) => cause, |
| 90 | }), |
| 91 | ).then((exit) => { |
| 92 | if (!cancelled && Exit.isSuccess(exit)) { |
| 93 | setLatestVersion(exit.value?.[fetchChannel] ?? null); |
| 94 | } |
| 95 | }); |
| 96 | return () => { |
| 97 | cancelled = true; |
| 98 | }; |
| 99 | }, [fetchChannel]); |
| 100 | |
| 101 | const updateAvailable = isUpdateAvailable(currentVersion, latestVersion); |
| 102 | |
| 103 | return { latestVersion, updateAvailable, channel: displayChannel }; |
| 104 | } |
| 105 | |
| 106 | // ── Card chrome ────────────────────────────────────────────────────────── |
| 107 |
no test coverage detected