From 08d730848653fff44bae4a73139026bbd1e89800 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Mon, 6 Apr 2026 13:58:11 +0800 Subject: [PATCH] Gate analytics and cache public API requests --- frontend/app/api/analytics/events/route.ts | 6 + frontend/app/api/cities/route.ts | 11 +- frontend/app/api/city/[name]/route.ts | 4 +- frontend/app/api/city/[name]/summary/route.ts | 17 +- frontend/app/api/healthz/route.ts | 4 +- frontend/app/api/history/[name]/route.ts | 7 +- frontend/app/api/vitals/route.ts | 17 + frontend/app/layout.tsx | 6 +- .../observability/WebVitalsReporter.tsx | 6 + frontend/hooks/useDashboardStore.tsx | 3 + frontend/lib/app-analytics.ts | 5 +- frontend/lib/backend-auth.ts | 8 +- frontend/package-lock.json | 327 ++---------------- frontend/package.json | 2 - 14 files changed, 114 insertions(+), 309 deletions(-) diff --git a/frontend/app/api/analytics/events/route.ts b/frontend/app/api/analytics/events/route.ts index 73f8bb8c..4a895a2a 100644 --- a/frontend/app/api/analytics/events/route.ts +++ b/frontend/app/api/analytics/events/route.ts @@ -5,8 +5,14 @@ import { } from "@/lib/backend-auth"; const API_BASE = process.env.POLYWEATHER_API_BASE_URL; +const ANALYTICS_ENABLED = + process.env.NEXT_PUBLIC_POLYWEATHER_APP_ANALYTICS === "true"; export async function POST(req: NextRequest) { + if (!ANALYTICS_ENABLED) { + return new NextResponse(null, { status: 204 }); + } + if (!API_BASE) { return NextResponse.json( { error: "POLYWEATHER_API_BASE_URL is not configured" }, diff --git a/frontend/app/api/cities/route.ts b/frontend/app/api/cities/route.ts index df4c5c3d..6500b8f9 100644 --- a/frontend/app/api/cities/route.ts +++ b/frontend/app/api/cities/route.ts @@ -18,10 +18,15 @@ export async function GET(req: NextRequest) { } try { - const auth = await buildBackendRequestHeaders(req); - const res = await fetch(`${API_BASE}/api/cities`, { + const auth = await buildBackendRequestHeaders(req, { + includeSupabaseIdentity: false, + }); + const fetchOptions = { headers: auth.headers, - cache: "no-store", + next: { revalidate: 300 }, + } as const; + const res = await fetch(`${API_BASE}/api/cities`, { + ...fetchOptions, }); if (!res.ok) { const raw = await res.text(); diff --git a/frontend/app/api/city/[name]/route.ts b/frontend/app/api/city/[name]/route.ts index c0a17fe3..7331cedf 100644 --- a/frontend/app/api/city/[name]/route.ts +++ b/frontend/app/api/city/[name]/route.ts @@ -23,7 +23,9 @@ export async function GET( const url = `${API_BASE}/api/city/${encodeURIComponent(name)}?force_refresh=${forceRefresh}`; try { - const auth = await buildBackendRequestHeaders(req); + const auth = await buildBackendRequestHeaders(req, { + includeSupabaseIdentity: false, + }); const res = await fetch(url, { headers: auth.headers, cache: "no-store", diff --git a/frontend/app/api/city/[name]/summary/route.ts b/frontend/app/api/city/[name]/summary/route.ts index 581387b6..e8f5d634 100644 --- a/frontend/app/api/city/[name]/summary/route.ts +++ b/frontend/app/api/city/[name]/summary/route.ts @@ -25,10 +25,21 @@ export async function GET( const url = `${API_BASE}/api/city/${encodeURIComponent(name)}/summary?force_refresh=${forceRefresh}`; try { - const auth = await buildBackendRequestHeaders(req); + const auth = await buildBackendRequestHeaders(req, { + includeSupabaseIdentity: false, + }); + const fetchOptions = + bypassCache + ? { + headers: auth.headers, + cache: "no-store" as const, + } + : { + headers: auth.headers, + next: { revalidate: 20 }, + }; const res = await fetch(url, { - headers: auth.headers, - cache: "no-store", + ...fetchOptions, }); if (!res.ok) { const raw = await res.text(); diff --git a/frontend/app/api/healthz/route.ts b/frontend/app/api/healthz/route.ts index 66ffb3a1..04515f3a 100644 --- a/frontend/app/api/healthz/route.ts +++ b/frontend/app/api/healthz/route.ts @@ -15,7 +15,9 @@ export async function GET(req: NextRequest) { } try { - const auth = await buildBackendRequestHeaders(req); + const auth = await buildBackendRequestHeaders(req, { + includeSupabaseIdentity: false, + }); const res = await fetch(`${API_BASE}/healthz`, { headers: auth.headers, cache: "no-store", diff --git a/frontend/app/api/history/[name]/route.ts b/frontend/app/api/history/[name]/route.ts index f2d15971..9dec7f4d 100644 --- a/frontend/app/api/history/[name]/route.ts +++ b/frontend/app/api/history/[name]/route.ts @@ -24,9 +24,12 @@ export async function GET( try { const auth = await buildBackendRequestHeaders(req); - const res = await fetch(url, { + const fetchOptions = { headers: auth.headers, - cache: "no-store", + next: { revalidate: 60 }, + } as const; + const res = await fetch(url, { + ...fetchOptions, }); if (!res.ok) { const raw = await res.text(); diff --git a/frontend/app/api/vitals/route.ts b/frontend/app/api/vitals/route.ts index 95f4f284..923607bb 100644 --- a/frontend/app/api/vitals/route.ts +++ b/frontend/app/api/vitals/route.ts @@ -5,6 +5,9 @@ import { recordVitalsSample, } from "@/lib/vitals-store"; +const WEB_VITALS_ENABLED = + process.env.NEXT_PUBLIC_POLYWEATHER_WEB_VITALS === "true"; + type VitalsPayload = { id?: string; metric?: string; @@ -15,6 +18,10 @@ type VitalsPayload = { }; export async function POST(request: Request) { + if (!WEB_VITALS_ENABLED) { + return new NextResponse(null, { status: 204 }); + } + try { const payload = (await request.json()) as VitalsPayload; const metric = normalizeMetricName(payload.metric); @@ -56,6 +63,16 @@ export async function POST(request: Request) { } export async function GET(request: Request) { + if (!WEB_VITALS_ENABLED) { + return NextResponse.json({ + ok: true, + disabled: true, + generatedAt: Date.now(), + sampleCount: 0, + routes: {}, + }); + } + const { searchParams } = new URL(request.url); const targetRoute = String(searchParams.get("route") || "").trim(); const summary = getVitalsSummary(); diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index c8ded1fe..ba441495 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,5 +1,4 @@ import type { Metadata } from "next"; -import { Analytics } from "@vercel/analytics/react"; import "./globals.css"; export const metadata: Metadata = { @@ -31,10 +30,7 @@ export default function RootLayout({ rel="stylesheet" /> - - {children} - - + {children} ); } diff --git a/frontend/components/observability/WebVitalsReporter.tsx b/frontend/components/observability/WebVitalsReporter.tsx index e1f025b8..b2c24d72 100644 --- a/frontend/components/observability/WebVitalsReporter.tsx +++ b/frontend/components/observability/WebVitalsReporter.tsx @@ -4,10 +4,16 @@ import { usePathname } from "next/navigation"; import { useReportWebVitals } from "next/web-vitals"; const TRACKED_METRICS = new Set(["INP", "LCP", "FCP"]); +const WEB_VITALS_ENABLED = + process.env.NEXT_PUBLIC_POLYWEATHER_WEB_VITALS === "true"; export function WebVitalsReporter() { const pathname = usePathname(); + if (!WEB_VITALS_ENABLED) { + return null; + } + useReportWebVitals((metric) => { if (!TRACKED_METRICS.has(metric.name)) { return; diff --git a/frontend/hooks/useDashboardStore.tsx b/frontend/hooks/useDashboardStore.tsx index adf8dbfb..5ba17c3f 100644 --- a/frontend/hooks/useDashboardStore.tsx +++ b/frontend/hooks/useDashboardStore.tsx @@ -88,6 +88,8 @@ function getMarketScanCacheKey(cityName: string, targetDate?: string | null) { const SELECTED_CITY_STORAGE_KEY = "polyWeather_selected_city_v1"; const BACKGROUND_SUMMARY_REFRESH_MS = 30_000; +const EAGER_CITY_SUMMARIES_ENABLED = + process.env.NEXT_PUBLIC_POLYWEATHER_EAGER_CITY_SUMMARIES === "true"; export function DashboardStoreProvider({ children, @@ -392,6 +394,7 @@ export function DashboardStoreProvider({ ]); useEffect(() => { + if (!EAGER_CITY_SUMMARIES_ENABLED) return; if (!cities.length) return; const queue = cities diff --git a/frontend/lib/app-analytics.ts b/frontend/lib/app-analytics.ts index 9b27436d..1d2c3272 100644 --- a/frontend/lib/app-analytics.ts +++ b/frontend/lib/app-analytics.ts @@ -1,5 +1,8 @@ "use client"; +const ANALYTICS_ENABLED = + process.env.NEXT_PUBLIC_POLYWEATHER_APP_ANALYTICS === "true"; + type TrackableAnalyticsEvent = | "signup_completed" | "dashboard_active" @@ -68,7 +71,7 @@ export function trackAppEvent( eventType: TrackableAnalyticsEvent, payload: Record = {}, ) { - if (!isClient()) return; + if (!isClient() || !ANALYTICS_ENABLED) return; const body = { event_type: eventType, client_id: getAnalyticsClientId() || undefined, diff --git a/frontend/lib/backend-auth.ts b/frontend/lib/backend-auth.ts index 275def33..8289d381 100644 --- a/frontend/lib/backend-auth.ts +++ b/frontend/lib/backend-auth.ts @@ -11,6 +11,10 @@ type HeaderBuildResult = { response: NextResponse | null; }; +type HeaderBuildOptions = { + includeSupabaseIdentity?: boolean; +}; + function extractBearerToken(headerValue: string | null) { if (!headerValue) return ""; const parts = headerValue.trim().split(/\s+/); @@ -22,6 +26,7 @@ function extractBearerToken(headerValue: string | null) { export async function buildBackendRequestHeaders( request: NextRequest, + options?: HeaderBuildOptions, ): Promise { const headers = new Headers({ Accept: "application/json", @@ -32,7 +37,8 @@ export async function buildBackendRequestHeaders( } const incomingAuth = extractBearerToken(request.headers.get("authorization")); - if (hasSupabaseServerEnv()) { + const includeSupabaseIdentity = options?.includeSupabaseIdentity !== false; + if (hasSupabaseServerEnv() && includeSupabaseIdentity) { const passthroughResponse = new NextResponse(null, { status: 200 }); const supabase = createSupabaseRouteClient(request, passthroughResponse); const { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 098fe06b..d079249f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,8 +11,6 @@ "@radix-ui/react-slot": "^1.1.2", "@supabase/ssr": "^0.5.2", "@supabase/supabase-js": "^2.57.2", - "@vercel/analytics": "^1.6.1", - "@vercel/speed-insights": "^2.0.0", "@walletconnect/ethereum-provider": "^2.23.8", "chart.js": "^4.5.1", "class-variance-authority": "^0.7.1", @@ -2054,47 +2052,6 @@ } } }, - "node_modules/@solana/kit": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/kit/-/kit-5.5.1.tgz", - "integrity": "sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ==", - "optional": true, - "dependencies": { - "@solana/accounts": "5.5.1", - "@solana/addresses": "5.5.1", - "@solana/codecs": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/instruction-plans": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/offchain-messages": "5.5.1", - "@solana/plugin-core": "5.5.1", - "@solana/programs": "5.5.1", - "@solana/rpc": "5.5.1", - "@solana/rpc-api": "5.5.1", - "@solana/rpc-parsed-types": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-subscriptions": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/signers": "5.5.1", - "@solana/sysvars": "5.5.1", - "@solana/transaction-confirmation": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@solana/nominal-types": { "version": "5.5.1", "resolved": "https://registry.npmmirror.com/@solana/nominal-types/-/nominal-types-5.5.1.tgz", @@ -2846,6 +2803,7 @@ "version": "2.99.1", "resolved": "https://registry.npmmirror.com/@supabase/supabase-js/-/supabase-js-2.99.1.tgz", "integrity": "sha512-5MRoYD9ffXq8F6a036dm65YoSHisC3by/d22mauKE99Vrwf792KxYIIr/iqCX7E4hkuugbPZ5EGYHTB7MKy6Vg==", + "peer": true, "dependencies": { "@supabase/auth-js": "2.99.1", "@supabase/functions-js": "2.99.1", @@ -2918,6 +2876,7 @@ "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "devOptional": true, + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2977,80 +2936,6 @@ "@types/node": "*" } }, - "node_modules/@vercel/analytics": { - "version": "1.6.1", - "resolved": "https://registry.npmmirror.com/@vercel/analytics/-/analytics-1.6.1.tgz", - "integrity": "sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==", - "peerDependencies": { - "@remix-run/react": "^2", - "@sveltejs/kit": "^1 || ^2", - "next": ">= 13", - "react": "^18 || ^19 || ^19.0.0-rc", - "svelte": ">= 4", - "vue": "^3", - "vue-router": "^4" - }, - "peerDependenciesMeta": { - "@remix-run/react": { - "optional": true - }, - "@sveltejs/kit": { - "optional": true - }, - "next": { - "optional": true - }, - "react": { - "optional": true - }, - "svelte": { - "optional": true - }, - "vue": { - "optional": true - }, - "vue-router": { - "optional": true - } - } - }, - "node_modules/@vercel/speed-insights": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@vercel/speed-insights/-/speed-insights-2.0.0.tgz", - "integrity": "sha512-jwkNcrTeafWxjmWq4AHBaptSqZiJkYU5adLC9QBSqeim0GcqDMgN5Ievh8OG1rJ6W3A4l1oiP7qr9CWxGuzu3w==", - "peerDependencies": { - "@sveltejs/kit": "^1 || ^2", - "next": ">= 13", - "nuxt": ">= 3", - "react": "^18 || ^19 || ^19.0.0-rc", - "svelte": ">= 4", - "vue": "^3", - "vue-router": "^4" - }, - "peerDependenciesMeta": { - "@sveltejs/kit": { - "optional": true - }, - "next": { - "optional": true - }, - "nuxt": { - "optional": true - }, - "react": { - "optional": true - }, - "svelte": { - "optional": true - }, - "vue": { - "optional": true - }, - "vue-router": { - "optional": true - } - } - }, "node_modules/@wallet-standard/base": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@wallet-standard/base/-/base-1.1.0.tgz", @@ -3209,20 +3094,6 @@ "ws": "^7.5.1" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", @@ -3651,17 +3522,6 @@ "postcss": "^8.1.0" } }, - "node_modules/axios": { - "version": "1.13.6", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", - "optional": true, - "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/axios-retry": { "version": "4.5.0", "resolved": "https://registry.npmmirror.com/axios-retry/-/axios-retry-4.5.0.tgz", @@ -3805,6 +3665,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3850,19 +3711,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/bufferutil": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bufferutil/-/bufferutil-4.1.0.tgz", - "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -4783,20 +4631,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "optional": true }, - "node_modules/jayson/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/jayson/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", @@ -4823,6 +4657,7 @@ "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -4850,7 +4685,8 @@ "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz", - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "peer": true }, "node_modules/lilconfig": { "version": "3.1.3", @@ -5384,6 +5220,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -5608,6 +5445,7 @@ "version": "19.2.4", "resolved": "https://registry.npmmirror.com/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5616,6 +5454,7 @@ "version": "19.2.4", "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -6118,6 +5957,7 @@ "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "peer": true, "engines": { "node": ">=12" }, @@ -6158,6 +5998,7 @@ "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6550,6 +6391,7 @@ "version": "8.19.0", "resolved": "https://registry.npmmirror.com/ws/-/ws-8.19.0.tgz", "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "peer": true, "engines": { "node": ">=10.0.0" }, @@ -6604,15 +6446,6 @@ "node": ">=6" } }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/zustand": { "version": "5.0.3", "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.3.tgz", @@ -7883,8 +7716,7 @@ "requires": {} }, "@solana/instruction-plans": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/instruction-plans/-/instruction-plans-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/instruction-plans/-/instruction-plans-5.5.1.tgz", "integrity": "sha512-7z3CB7YMcFKuVvgcnNY8bY6IsZ8LG61Iytbz7HpNVGX2u1RthOs1tRW8luTzSG1MPL0Ox7afyAVMYeFqSPHnaQ==", "optional": true, "requires": { @@ -7919,36 +7751,6 @@ "@solana/nominal-types": "5.5.1" } }, - "@solana/kit": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/kit/-/kit-5.5.1.tgz", - "integrity": "sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ==", - "optional": true, - "requires": { - "@solana/accounts": "5.5.1", - "@solana/addresses": "5.5.1", - "@solana/codecs": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/instruction-plans": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/offchain-messages": "5.5.1", - "@solana/plugin-core": "5.5.1", - "@solana/programs": "5.5.1", - "@solana/rpc": "5.5.1", - "@solana/rpc-api": "5.5.1", - "@solana/rpc-parsed-types": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-subscriptions": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/signers": "5.5.1", - "@solana/sysvars": "5.5.1", - "@solana/transaction-confirmation": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" - } - }, "@solana/nominal-types": { "version": "5.5.1", "resolved": "https://registry.npmmirror.com/@solana/nominal-types/-/nominal-types-5.5.1.tgz", @@ -7986,15 +7788,13 @@ } }, "@solana/plugin-core": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/plugin-core/-/plugin-core-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/plugin-core/-/plugin-core-5.5.1.tgz", "integrity": "sha512-VUZl30lDQFJeiSyNfzU1EjYt2QZvoBFKEwjn1lilUJw7KgqD5z7mbV7diJhT+dLFs36i0OsjXvq5kSygn8YJ3A==", "optional": true, "requires": {} }, "@solana/programs": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/programs/-/programs-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/programs/-/programs-5.5.1.tgz", "integrity": "sha512-7U9kn0Jsx1NuBLn5HRTFYh78MV4XN145Yc3WP/q5BlqAVNlMoU9coG5IUTJIG847TUqC1lRto3Dnpwm6T4YRpA==", "optional": true, "requires": { @@ -8176,8 +7976,7 @@ } }, "@solana/signers": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/signers/-/signers-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/signers/-/signers-5.5.1.tgz", "integrity": "sha512-FY0IVaBT2kCAze55vEieR6hag4coqcuJ31Aw3hqRH7mv6sV8oqwuJmUrx+uFwOp1gwd5OEAzlv6N4hOOple4sQ==", "optional": true, "requires": { @@ -8202,8 +8001,7 @@ } }, "@solana/sysvars": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/sysvars/-/sysvars-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/sysvars/-/sysvars-5.5.1.tgz", "integrity": "sha512-k3Quq87Mm+geGUu1GWv6knPk0ALsfY6EKSJGw9xUJDHzY/RkYSBnh0RiOrUhtFm2TDNjOailg8/m0VHmi3reFA==", "optional": true, "requires": { @@ -8214,8 +8012,7 @@ } }, "@solana/transaction-confirmation": { - "version": "5.5.1", - "resolved": "https://registry.npmmirror.com/@solana/transaction-confirmation/-/transaction-confirmation-5.5.1.tgz", + "version": "https://registry.npmmirror.com/@solana/transaction-confirmation/-/transaction-confirmation-5.5.1.tgz", "integrity": "sha512-j4mKlYPHEyu+OD7MBt3jRoX4ScFgkhZC6H65on4Fux6LMScgivPJlwnKoZMnsgxFgWds0pl+BYzSiALDsXlYtw==", "optional": true, "requires": { @@ -8403,6 +8200,7 @@ "version": "2.99.1", "resolved": "https://registry.npmmirror.com/@supabase/supabase-js/-/supabase-js-2.99.1.tgz", "integrity": "sha512-5MRoYD9ffXq8F6a036dm65YoSHisC3by/d22mauKE99Vrwf792KxYIIr/iqCX7E4hkuugbPZ5EGYHTB7MKy6Vg==", + "peer": true, "requires": { "@supabase/auth-js": "2.99.1", "@supabase/functions-js": "2.99.1", @@ -8472,6 +8270,7 @@ "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "devOptional": true, + "peer": true, "requires": { "csstype": "^3.2.2" } @@ -8529,18 +8328,6 @@ "@types/node": "*" } }, - "@vercel/analytics": { - "version": "1.6.1", - "resolved": "https://registry.npmmirror.com/@vercel/analytics/-/analytics-1.6.1.tgz", - "integrity": "sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg==", - "requires": {} - }, - "@vercel/speed-insights": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@vercel/speed-insights/-/speed-insights-2.0.0.tgz", - "integrity": "sha512-jwkNcrTeafWxjmWq4AHBaptSqZiJkYU5adLC9QBSqeim0GcqDMgN5Ievh8OG1rJ6W3A4l1oiP7qr9CWxGuzu3w==", - "requires": {} - }, "@wallet-standard/base": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@wallet-standard/base/-/base-1.1.0.tgz", @@ -8696,16 +8483,6 @@ "ws": "^7.5.1" }, "dependencies": { - "utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "ws": { "version": "7.5.10", "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", @@ -9021,17 +8798,6 @@ "postcss-value-parser": "^4.2.0" } }, - "axios": { - "version": "1.13.6", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", - "optional": true, - "requires": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" - } - }, "axios-retry": { "version": "4.5.0", "resolved": "https://registry.npmmirror.com/axios-retry/-/axios-retry-4.5.0.tgz", @@ -9124,6 +8890,7 @@ "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, + "peer": true, "requires": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -9149,15 +8916,6 @@ "ieee754": "^1.2.1" } }, - "bufferutil": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bufferutil/-/bufferutil-4.1.0.tgz", - "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", - "optional": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -9557,14 +9315,12 @@ } }, "follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "version": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "optional": true }, "form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", + "version": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "optional": true, "requires": { @@ -9821,16 +9577,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "optional": true }, - "utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "ws": { "version": "7.5.10", "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", @@ -9844,7 +9590,8 @@ "version": "1.21.7", "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true + "dev": true, + "peer": true }, "jose": { "version": "6.2.1", @@ -9866,7 +9613,8 @@ "leaflet": { "version": "1.9.4", "resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz", - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "peer": true }, "lilconfig": { "version": "3.1.3", @@ -10221,6 +9969,7 @@ "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, + "peer": true, "requires": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -10298,8 +10047,7 @@ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==" }, "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "version": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "optional": true }, @@ -10333,12 +10081,14 @@ "react": { "version": "19.2.4", "resolved": "https://registry.npmmirror.com/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==" + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "peer": true }, "react-dom": { "version": "19.2.4", "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "peer": true, "requires": { "scheduler": "^0.27.0" } @@ -10681,7 +10431,8 @@ "version": "4.0.3", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true + "dev": true, + "peer": true } } }, @@ -10714,7 +10465,8 @@ "version": "5.9.3", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true + "devOptional": true, + "peer": true }, "ufo": { "version": "1.6.3", @@ -10898,6 +10650,7 @@ "version": "8.19.0", "resolved": "https://registry.npmmirror.com/ws/-/ws-8.19.0.tgz", "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "peer": true, "requires": {} }, "y18n": { @@ -10932,12 +10685,6 @@ "decamelize": "^1.2.0" } }, - "zod": { - "version": "3.25.76", - "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "optional": true - }, "zustand": { "version": "5.0.3", "resolved": "https://registry.npmmirror.com/zustand/-/zustand-5.0.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1f2116ce..e0878198 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,8 +12,6 @@ "@radix-ui/react-slot": "^1.1.2", "@supabase/ssr": "^0.5.2", "@supabase/supabase-js": "^2.57.2", - "@vercel/analytics": "^1.6.1", - "@vercel/speed-insights": "^2.0.0", "@walletconnect/ethereum-provider": "^2.23.8", "chart.js": "^4.5.1", "class-variance-authority": "^0.7.1",