chore(debug): add /debug-env page to verify Vercel env-var presence
Server-side gerenderde tabel die per env-var (DATABASE_URL, DIRECT_URL, SESSION_SECRET) toont of ie gezet is, lengte, hostname (van DB-URLs) en of het de Neon-pooler is. Geen secrets in de output. Doel: bevestigen dat onze Vercel-env-config correct werd opgeslagen na de eerdere ENOTFOUND 'base'-error. Tijdelijk; verwijderen zodra de config is gevalideerd. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f6132960a5
commit
8afbc4f6c4
1 changed files with 112 additions and 0 deletions
112
app/debug-env/page.tsx
Normal file
112
app/debug-env/page.tsx
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
// TIJDELIJKE debug-pagina om te checken of env-vars op deze deployment
|
||||||
|
// daadwerkelijk een (juiste) waarde hebben. Geen secrets gelekt — alleen
|
||||||
|
// metadata: lengte, hostname en pooled-flag voor DB-URLs.
|
||||||
|
//
|
||||||
|
// VERWIJDEREN zodra env-config op Vercel bevestigd is.
|
||||||
|
|
||||||
|
import { headers } from 'next/headers'
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic'
|
||||||
|
export const runtime = 'nodejs'
|
||||||
|
|
||||||
|
interface VarStatus {
|
||||||
|
name: string
|
||||||
|
set: boolean
|
||||||
|
length: number
|
||||||
|
host?: string
|
||||||
|
pooled?: boolean
|
||||||
|
parseError?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function inspectUrl(name: string, raw: string | undefined): VarStatus {
|
||||||
|
if (!raw) return { name, set: false, length: 0 }
|
||||||
|
try {
|
||||||
|
const url = new URL(raw)
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
set: true,
|
||||||
|
length: raw.length,
|
||||||
|
host: url.hostname,
|
||||||
|
pooled: url.hostname.includes('pooler.'),
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
set: true,
|
||||||
|
length: raw.length,
|
||||||
|
parseError: e instanceof Error ? e.message : String(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inspectSecret(name: string, raw: string | undefined): VarStatus {
|
||||||
|
if (!raw) return { name, set: false, length: 0 }
|
||||||
|
return { name, set: true, length: raw.length }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function DebugEnvPage() {
|
||||||
|
// Force dynamic so each visit reads runtime env (niet build-time gecached)
|
||||||
|
await headers()
|
||||||
|
|
||||||
|
const vars: VarStatus[] = [
|
||||||
|
inspectUrl('DATABASE_URL', process.env.DATABASE_URL),
|
||||||
|
inspectUrl('DIRECT_URL', process.env.DIRECT_URL),
|
||||||
|
inspectSecret('SESSION_SECRET', process.env.SESSION_SECRET),
|
||||||
|
]
|
||||||
|
|
||||||
|
const node = process.env.NODE_ENV ?? '(unset)'
|
||||||
|
const vercel = process.env.VERCEL_ENV ?? '(unset)'
|
||||||
|
const url = process.env.VERCEL_URL ?? '(unset)'
|
||||||
|
const region = process.env.VERCEL_REGION ?? '(unset)'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ fontFamily: 'monospace', padding: 16, maxWidth: 1000 }}>
|
||||||
|
<h1 style={{ fontSize: 18, fontWeight: 'bold' }}>Env-var debug</h1>
|
||||||
|
<p style={{ fontSize: 13, color: '#666' }}>
|
||||||
|
Server-side gerenderd. Toont alleen metadata, geen waardes. Verwijderen na env-config check.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 style={{ fontSize: 15, marginTop: 16 }}>Runtime</h2>
|
||||||
|
<table style={{ borderCollapse: 'collapse', fontSize: 13 }}>
|
||||||
|
<tbody>
|
||||||
|
<tr><td style={{ padding: 4, paddingRight: 16 }}>NODE_ENV</td><td>{node}</td></tr>
|
||||||
|
<tr><td style={{ padding: 4 }}>VERCEL_ENV</td><td>{vercel}</td></tr>
|
||||||
|
<tr><td style={{ padding: 4 }}>VERCEL_URL</td><td>{url}</td></tr>
|
||||||
|
<tr><td style={{ padding: 4 }}>VERCEL_REGION</td><td>{region}</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2 style={{ fontSize: 15, marginTop: 24 }}>Variables</h2>
|
||||||
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
|
||||||
|
<thead>
|
||||||
|
<tr style={{ background: '#f0f0f0', textAlign: 'left' }}>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>name</th>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>set</th>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>length</th>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>host</th>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>pooled</th>
|
||||||
|
<th style={{ padding: 6, border: '1px solid #ddd' }}>parse_error</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{vars.map((v) => (
|
||||||
|
<tr key={v.name}>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd' }}>{v.name}</td>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd', color: v.set ? 'green' : 'red' }}>
|
||||||
|
{v.set ? 'yes' : 'NO'}
|
||||||
|
</td>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd' }}>{v.length}</td>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd' }}>{v.host ?? '—'}</td>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd', color: v.pooled ? 'orange' : 'inherit' }}>
|
||||||
|
{v.pooled === undefined ? '—' : v.pooled ? 'yes (LISTEN may not work)' : 'no'}
|
||||||
|
</td>
|
||||||
|
<td style={{ padding: 6, border: '1px solid #ddd', color: 'red' }}>
|
||||||
|
{v.parseError ?? '—'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue