1
0
forked from maik/IPFS-portal

fix: bw/stats 404, gateway links, history crash

- swr.ts: remove useBandwidth(), drop bw from useDashboard()
- events/route.ts: skip bandwidth SSE (Kubo 0.28.0 unsupported)
- usage/page.tsx: remove getBWStats call + bw references
- helpers.ts: gatewayLink -> ipfs.maos.dedyn.io (subdomain only)
- upload/page.tsx: fix local gatewayLink (subdomain only)
- storage.ts: update default gatewayUrl, add defensive getHistory()
This commit is contained in:
maikrolf
2026-07-05 17:03:18 +02:00
9 changed files with 35 additions and 20 deletions
+1 -1
View File
@@ -83,7 +83,7 @@ services:
- NEXT_TELEMETRY_DISABLED=1 - NEXT_TELEMETRY_DISABLED=1
- USER_API_BASE=http://192.168.1.176:8444 - USER_API_BASE=http://192.168.1.176:8444
- USER_API_ADMIN_KEY=maos-admin-2024 - USER_API_ADMIN_KEY=maos-admin-2024
- KUBO_API_URL=http://tom1687.no-ip.org:8443 - KUBO_API_URL=http://192.168.1.176:8443
- KUBO_BASIC_AUTH=portal:ipfs-portal-2024 - KUBO_BASIC_AUTH=portal:ipfs-portal-2024
healthcheck: healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3445/api/health"] test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3445/api/health"]
+2 -7
View File
@@ -8,7 +8,6 @@
"name": "@maos/ipfs-portal", "name": "@maos/ipfs-portal",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@maos/ipfs-portal": "file:",
"@tailwindcss/postcss": "^4.3.1", "@tailwindcss/postcss": "^4.3.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"jose": "^6.2.3", "jose": "^6.2.3",
@@ -22,8 +21,8 @@
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.61.1", "@playwright/test": "^1.61.1",
"@types/node": "^22.0.0", "@types/node": "22.20.0",
"@types/react": "^19.0.0", "@types/react": "19.2.17",
"@types/react-dom": "^19.0.0", "@types/react-dom": "^19.0.0",
"tailwindcss": "^4.0.0", "tailwindcss": "^4.0.0",
"typescript": "^5.8.0", "typescript": "^5.8.0",
@@ -590,10 +589,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
} }
}, },
"node_modules/@maos/ipfs-portal": {
"resolved": "",
"link": true
},
"node_modules/@napi-rs/wasm-runtime": { "node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.6", "version": "1.1.6",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
+3 -3
View File
@@ -7,10 +7,10 @@
"dev": "next dev --port 3445", "dev": "next dev --port 3445",
"dev:webpack": "next dev --port 3445 --webpack", "dev:webpack": "next dev --port 3445 --webpack",
"build": "next build", "build": "next build",
"start": "next start",
"export": "next build && npx serve out" "export": "next build && npx serve out"
}, },
"dependencies": { "dependencies": {
"@maos/ipfs-portal": "file:",
"@tailwindcss/postcss": "^4.3.1", "@tailwindcss/postcss": "^4.3.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"jose": "^6.2.3", "jose": "^6.2.3",
@@ -24,8 +24,8 @@
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.61.1", "@playwright/test": "^1.61.1",
"@types/node": "^22.0.0", "@types/node": "22.20.0",
"@types/react": "^19.0.0", "@types/react": "19.2.17",
"@types/react-dom": "^19.0.0", "@types/react-dom": "^19.0.0",
"tailwindcss": "^4.0.0", "tailwindcss": "^4.0.0",
"typescript": "^5.8.0", "typescript": "^5.8.0",
+10 -3
View File
@@ -69,6 +69,11 @@ self.addEventListener('fetch', (event) => {
// Same-origin only // Same-origin only
if (url.origin !== self.location.origin) return; if (url.origin !== self.location.origin) return;
// Only cache GET/HEAD — POST/PUT/DELETE/OPTIONS can't use Cache API
if (request.method !== 'GET' && request.method !== 'HEAD') {
return; // pass through, no caching
}
// 1. Static assets → cache-first // 1. Static assets → cache-first
if (isStaticAsset(url)) { if (isStaticAsset(url)) {
event.respondWith(cacheFirst(request, STATIC_CACHE)); event.respondWith(cacheFirst(request, STATIC_CACHE));
@@ -98,7 +103,8 @@ async function cacheFirst(request, cacheName) {
if (cached) return cached; if (cached) return cached;
try { try {
const response = await fetch(request); const response = await fetch(request);
if (response.ok) { // Cache API supports GET/HEAD only
if (response.ok && request.method === 'GET') {
const cache = await caches.open(cacheName); const cache = await caches.open(cacheName);
cache.put(request, response.clone()); cache.put(request, response.clone());
} }
@@ -111,7 +117,8 @@ async function cacheFirst(request, cacheName) {
async function networkFirst(request, cacheName) { async function networkFirst(request, cacheName) {
try { try {
const response = await fetch(request); const response = await fetch(request);
if (response.ok) { // Cache API supports GET/HEAD only — POST/PUT/DELETE must be skipped
if (response.ok && request.method === 'GET') {
const cache = await caches.open(cacheName); const cache = await caches.open(cacheName);
cache.put(request, response.clone()); cache.put(request, response.clone());
} }
@@ -129,7 +136,7 @@ async function staleWhileRevalidate(request, cacheName) {
const fetchPromise = fetch(request) const fetchPromise = fetch(request)
.then((response) => { .then((response) => {
if (response.ok) cache.put(request, response.clone()); if (response.ok && request.method === 'GET') cache.put(request, response.clone());
return response; return response;
}) })
.catch(() => cached); .catch(() => cached);
+1 -1
View File
@@ -17,7 +17,7 @@ import { NextRequest, NextResponse } from 'next/server';
import { createPublicClient, http, type Address, type Hash, type Chain } from 'viem'; import { createPublicClient, http, type Address, type Hash, type Chain } from 'viem';
import { IPFS_PORTAL_PAYMENT_ABI } from '@/lib/payment'; import { IPFS_PORTAL_PAYMENT_ABI } from '@/lib/payment';
const RPC_URL = process.env.ZKSYNC_RPC_URL || 'http://tom1687.no-ip.org:3050'; const RPC_URL = process.env.ZKSYNC_RPC_URL || 'http://192.168.1.176:3050';
const CONTRACT_ADDRESS = (process.env.PAYMENT_CONTRACT_ADDRESS || '0xCBc6b8aeea129c206F4836799621C833Bf8B9BDe') as Address; const CONTRACT_ADDRESS = (process.env.PAYMENT_CONTRACT_ADDRESS || '0xCBc6b8aeea129c206F4836799621C833Bf8B9BDe') as Address;
const zkSyncLocal: Chain = { const zkSyncLocal: Chain = {
+1 -1
View File
@@ -348,7 +348,7 @@ export default function PaymentPanel({
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-surface-400">Tx</span> <span className="text-surface-400">Tx</span>
<a <a
href={`http://tom1687.no-ip.org:3050/tx/${txHash}`} href={`http://192.168.1.176:3050/tx/${txHash}`}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="flex items-center gap-1 text-brand-400 hover:text-brand-300 font-mono" className="flex items-center gap-1 text-brand-400 hover:text-brand-300 font-mono"
+2 -2
View File
@@ -8,10 +8,10 @@ export const zkSyncLocal: Chain = {
name: 'zkSync Local', name: 'zkSync Local',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: { rpcUrls: {
default: { http: ['http://tom1687.no-ip.org:3050'] }, default: { http: ['http://192.168.1.176:3050'] },
}, },
blockExplorers: { blockExplorers: {
default: { name: 'Explorer', url: 'http://tom1687.no-ip.org:3050' }, default: { name: 'Explorer', url: 'http://192.168.1.176:3050' },
}, },
}; };
+2 -2
View File
@@ -56,8 +56,8 @@ const ZKSYNC_LOCAL_CHAIN = {
chainId: '0x10E', // 270 chainId: '0x10E', // 270
chainName: 'zkSync Local', chainName: 'zkSync Local',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: ['http://tom1687.no-ip.org:3050'], rpcUrls: ['http://192.168.1.176:3050'],
blockExplorerUrls: ['http://tom1687.no-ip.org:3050'], blockExplorerUrls: ['http://192.168.1.176:3050'],
}; };
/* ── EIP-6963 event-based provider discovery ── */ /* ── EIP-6963 event-based provider discovery ── */
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# IPFS-Portal PM2 start script — runs from /srv/apps/ipfs-portal
# Usage: pm2 start start-pm2.sh --name ipfs-portal
set -e
cd /srv/apps/ipfs-portal || { echo "ERROR: /srv/apps/ipfs-portal not found"; exit 1; }
echo "=== npm install ==="
npm install
echo "=== npm run build ==="
npm run build
echo "=== next start port ${PORT:=3005} ==="
# Consume any extra args PM2 passes (e.g. --port=3005)
shift "$(($# < 1 ? 0 : 1))" 2>/dev/null || true
exec npx next start --port "$PORT" "$@"