1
0
forked from maik/IPFS-portal

refactor: codebase opschoning — type safety, error handling, central config, page splits

- categorie A: alle catch(e: any) → catch(e: unknown) met instanceof check
- categorie B: stille .catch() logging toegevoegd (SWRegister, admin, upload, auth)
- categorie C: hardcoded 192.168.1.176 IPs vervangen door env var defaults
- categorie D: page files >250L gesplitst (history, settings, explorer, admin/payment,
  ipns, users, upload, dashboard) in helpers/components
- categorie E: eslint-disable vervangen in SearchInput.tsx
- src/lib/config.ts centrale config module (localhost defaults)
- CSP in next.config.ts dynamisch via env var
- deploy.sh: geen hardcoded IP meer (REQUIRED arg)
- lib/api/ lib/auth/ lib/wallet/ lib/search-index/ lib/storage/ gesplitst in modules
- ongebruikte bestanden verwijderd: api.ts, auth.tsx, wallet.ts, search-index.ts,
  PaymentPanel.tsx, SearchBar.tsx, proxy.ts, serve-static.js
This commit is contained in:
maikrolf
2026-07-19 15:35:18 +02:00
parent 88ce38a49e
commit f72b775379
144 changed files with 4644 additions and 10230 deletions
+28 -39
View File
@@ -2,47 +2,23 @@
import { useState, useEffect, useCallback } from 'react';
import PortalLayout from '@/app/layout-portal';
import { explorerLs, explorerCat, listPins } from '@/lib/api';
import type { IPFSEntry } from '@/lib/api';
import { explorerLs, explorerCat, type IPFSEntry } from '@/lib/api/explorer';
import { listPins } from '@/lib/api/pins';
import CIDInput from './components/CIDInput';
import DirectoryListing from './components/DirectoryListing';
import FilePreview from './components/FilePreview';
import Breadcrumbs from './components/Breadcrumbs';
import PinBadge from './components/PinBadge';
import GatewayLink from './components/GatewayLink';
import SearchBar from '@/components/SearchBar';
import SearchBar from '@/components/search';
import type { SearchResult } from '@/lib/search-index';
import { isTextFile, extractText, addToIndex, clearIndex, getIndexStats } from '@/lib/search-index';
import { Search, AlertCircle, RefreshCw, Database, Loader2 } from 'lucide-react';
import Skeleton from '@/components/Skeleton';
const RECENT_STORAGE_KEY = 'ipfs-explorer-recent-cids';
import ErrorBoundary from '@/components/ErrorBoundary';
interface BreadcrumbSegment {
cid: string;
name: string;
}
function loadRecentCids(): string[] {
if (typeof window === 'undefined') return [];
try {
const raw = localStorage.getItem(RECENT_STORAGE_KEY);
return raw ? (JSON.parse(raw) as string[]) : [];
} catch {
return [];
}
}
function saveRecentCid(cid: string) {
try {
const existing = loadRecentCids();
const updated = [cid, ...existing.filter((c) => c !== cid)].slice(0, 10);
localStorage.setItem(RECENT_STORAGE_KEY, JSON.stringify(updated));
} catch {
// localStorage write failed silently
}
}
type ExplorerState = 'idle' | 'loading' | 'resolving' | 'loaded' | 'error';
import { loadRecentCids, saveRecentCid, findFilename, type ExplorerState, type BreadcrumbSegment } from './helpers';
export default function ExplorerPage() {
const [cid, setCid] = useState('');
@@ -111,7 +87,8 @@ export default function ExplorerPage() {
try {
const content = await explorerCat(hash);
setPreviewContent(content);
} catch {
} catch (err) {
console.error('[ExplorerPage] Failed to fetch preview content:', err);
setPreviewContent(null);
} finally {
setPreviewLoading(false);
@@ -156,7 +133,8 @@ export default function ExplorerPage() {
});
indexed++;
}
} catch {
} catch (err) {
console.error('[ExplorerPage] Failed to index pin:', err);
failed++;
}
}
@@ -171,6 +149,7 @@ export default function ExplorerPage() {
return (
<PortalLayout>
<ErrorBoundary label="Verkenner">
{/* Page header */}
<div className="mb-6">
<h1 className="text-2xl font-bold text-white">IPFS Explorer</h1>
@@ -234,11 +213,22 @@ export default function ExplorerPage() {
</div>
)}
{/* Resolving IPNS */}
{/* Resolving IPNS — skeleton */}
{state === 'resolving' && (
<div className="glass rounded-xl p-8 flex flex-col items-center justify-center text-center animate-fade-in">
<RefreshCw className="w-5 h-5 text-accent-cyan animate-spin mb-3" />
<p className="text-sm text-surface-400">Resolving IPNS name...</p>
<div className="glass rounded-xl p-8 animate-fade-in">
<div className="flex items-center gap-3 mb-6">
<Skeleton className="h-5 w-48" />
<Skeleton className="h-5 w-28" />
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="glass rounded-xl p-5 space-y-3">
<Skeleton className="h-3 w-20" />
<Skeleton className="h-7 w-48" />
<Skeleton className="h-2 w-full" />
</div>
))}
</div>
</div>
)}
@@ -300,10 +290,9 @@ export default function ExplorerPage() {
)}
</div>
)}
</ErrorBoundary>
</PortalLayout>
);
}
function findFilename(entries: IPFSEntry[], hash: string): string | undefined {
return entries.find((e) => e.hash === hash)?.name;
}