diff --git a/src/components/Menu.svelte b/src/components/Menu.svelte
index 42c73e2..07e81f2 100644
--- a/src/components/Menu.svelte
+++ b/src/components/Menu.svelte
@@ -4,16 +4,8 @@
import { Badge } from '@/components/ui/badge';
import Separator from '@/components/ui/separator/separator.svelte';
import { currentUser, devmode } from '@/stores/session';
- import {
- Code,
- GitBranch,
- HelpCircle,
- Mail,
- Package,
- Pyramid,
- Rocket,
- Users
- } from 'lucide-svelte';
+ import { commitInfo } from '@/stores/github';
+ import { Code, HelpCircle, Mail, Package, Pyramid, Rocket } from 'lucide-svelte';
import { GitAltBrand, TelegramBrand } from 'svelte-awesome-icons';
import NotifyMe from './NotifyMe.svelte';
@@ -85,6 +77,8 @@
{#if $devmode}
RELEASE NAME:
- shippable intermediary
+ shippable intermediary
+ Commit: {$commitInfo.hash}
+ Height: {$commitInfo.count}
+
{/if}
diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts
index 8b5542b..1a3a36c 100644
--- a/src/lib/helpers.ts
+++ b/src/lib/helpers.ts
@@ -102,11 +102,6 @@ export async function getCuckPrice(): Promise {
});
}
-interface CommitInfo {
- count: number;
- hash: string;
-}
-
interface GitHubUrlParts {
owner: string;
repo: string;
@@ -114,7 +109,7 @@ interface GitHubUrlParts {
number?: string;
}
-class GitHubApiError extends Error {
+export class GitHubApiError extends Error {
constructor(
message: string,
public status?: number
@@ -124,7 +119,7 @@ class GitHubApiError extends Error {
}
}
-function parseGitHubUrl(url: URL): GitHubUrlParts {
+export function parseGitHubUrl(url: URL): GitHubUrlParts {
const parts = url.pathname.split('/').filter(Boolean);
if (parts.length < 2) {
throw new Error('Invalid GitHub URL');
@@ -137,38 +132,6 @@ function parseGitHubUrl(url: URL): GitHubUrlParts {
};
}
-async function fetchGitHubApi(apiUrl: URL): Promise {
- const response = await fetch(apiUrl);
- if (!response.ok) {
- throw new GitHubApiError(`HTTP error! status: ${response.status}`, response.status);
- }
- return response.json();
-}
-
-export async function getCommit(url: URL): Promise {
- try {
- const { owner, repo } = parseGitHubUrl(url);
- const apiURL = new URL(`https://api.github.com/repos/${owner}/${repo}/commits`);
- const json = await fetchGitHubApi(apiURL);
-
- if (!json[0]?.sha) {
- throw new GitHubApiError('Failed to fetch commit info: API returned unexpected data');
- }
-
- return {
- count: json.length,
- hash: json[0].sha
- };
- } catch (error) {
- if (error instanceof GitHubApiError) {
- throw error;
- }
- throw new Error(
- `Failed to fetch commit info: ${error instanceof Error ? error.message : String(error)}`
- );
- }
-}
-
export async function parseProblem(problem: string): Promise {
if (!isGitHubIssuesOrPullUrl(problem)) {
return undefined;
@@ -176,9 +139,15 @@ export async function parseProblem(problem: string): Promise
try {
const { owner, repo, number } = parseGitHubUrl(new URL(problem));
+
const apiURL = new URL(`https://api.github.com/repos/${owner}/${repo}/issues/${number}`);
- const { title } = await fetchGitHubApi(apiURL);
- return title;
+ const response = await fetch(apiURL);
+ if (!response.ok) {
+ throw new GitHubApiError(`HTTP error! status: ${response.status}`, response.status);
+ }
+
+ const json = await response.json();
+ return json.title;
} catch (error) {
console.error('Failed to parse problem:', error);
return undefined;
diff --git a/src/lib/stores/github.ts b/src/lib/stores/github.ts
new file mode 100644
index 0000000..446314d
--- /dev/null
+++ b/src/lib/stores/github.ts
@@ -0,0 +1,48 @@
+import { GitHubApiError, parseGitHubUrl } from '@/helpers';
+import { writable } from 'svelte/store';
+
+interface CommitInfo {
+ count: number;
+ hash: string;
+}
+
+let _c: CommitInfo = { hash: '', count: 0 };
+export const commitInfo = writable(_c);
+
+export async function getCommitInfo(url: URL): Promise {
+ try {
+ const { owner, repo } = parseGitHubUrl(url);
+ const apiURL = new URL(`https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`);
+
+ const response = await fetch(apiURL);
+ if (!response.ok) {
+ throw new GitHubApiError(`HTTP error! status: ${response.status}`, response.status);
+ }
+ const json = await response.json();
+
+ if (!json[0]?.sha) {
+ throw new GitHubApiError('Failed to fetch commit info: API returned unexpected data');
+ }
+ const totalCommits = parseLinkHeader(response.headers.get('Link'));
+
+ let r: CommitInfo = {
+ count: totalCommits,
+ hash: json[0].sha
+ };
+ commitInfo.set(r);
+ return r;
+ } catch (error) {
+ if (error instanceof GitHubApiError) {
+ throw error;
+ }
+ throw new Error(
+ `Failed to fetch commit info: ${error instanceof Error ? error.message : String(error)}`
+ );
+ }
+}
+
+function parseLinkHeader(header: string | null): number {
+ if (!header) return 0;
+ const matches = header.match(/page=(\d+)>; rel="last"/);
+ return matches ? parseInt(matches[1], 10) : 0;
+}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 9a6445a..9dc5ee7 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -7,6 +7,7 @@
import { onMount } from 'svelte';
import '../app.css';
import SidePanelLayout from '../layouts/SidePanelLayout.svelte';
+ import { getCommitInfo } from '@/stores/github';
let sessionStarted = false;
let connected = false;
@@ -29,6 +30,7 @@
onMount(() => {
getBitcoinTip();
+ getCommitInfo(new URL('https://github.com/nostrocket/hypergolic/'));
});
setInterval(