< Summary

Information
Class: debug.config.tsx
Assembly: app.routes
File(s): /home/runner/work/ClutterStock/ClutterStock/frontend/app/routes/debug.config.tsx
Tag: 58_25416222083
Line coverage
0%
Covered lines: 0
Uncovered lines: 17
Coverable lines: 17
Total lines: 163
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/ClutterStock/ClutterStock/frontend/app/routes/debug.config.tsx

#LineLine coverage
 1import { useMemo } from "react";
 2
 3import type { Route } from "./+types/debug.config";
 4import { getApiBase } from "~/constants/api";
 5import {
 6  isDebugConfigAllowed,
 7  pickDebugServerEnv,
 8  pickImportMetaEnvForDebug,
 9} from "~/lib/debug-config";
 10import { readPublicRuntimeConfigFromWindow } from "~/public-runtime-config";
 11
 012export async function loader(_args: Route.LoaderArgs) {
 013  if (!isDebugConfigAllowed()) {
 014    throw new Response(null, { status: 404 });
 15  }
 16
 017  return {
 18    serverEnv: pickDebugServerEnv(),
 19    apiBaseResolvedOnServer: getApiBase(),
 20  };
 21}
 22
 023export function meta(_args: Route.MetaArgs) {
 024  return [{ title: "Debug config | ClutterStock" }];
 25}
 26
 027function EnvTable({ rows }: { readonly rows: Record<string, string> }) {
 028  const entries = useMemo(
 29    () =>
 030      Object.entries(rows).sort(([a], [b]) => a.localeCompare(b, "en")),
 31    [rows],
 32  );
 033  return (
 34    <table className="w-full text-sm border-collapse">
 35      <thead>
 36        <tr className="border-b border-neutral-300 dark:border-neutral-600 text-left">
 37          <th className="py-2 pr-4 font-medium text-neutral-600 dark:text-neutral-400">
 38            Name
 39          </th>
 40          <th className="py-2 font-medium text-neutral-600 dark:text-neutral-400">
 41            Value
 42          </th>
 43        </tr>
 44      </thead>
 45      <tbody>
 046        {entries.map(([key, value]) => (
 047          <tr
 48            key={key}
 49            className="border-b border-neutral-200 dark:border-neutral-700 align-top"
 50          >
 51            <td className="py-2 pr-4 font-mono text-neutral-800 dark:text-neutral-200 whitespace-nowrap">
 52              {key}
 53            </td>
 54            <td className="py-2 font-mono text-neutral-700 dark:text-neutral-300 break-all">
 55              {value === "" ? (
 56                <span className="text-neutral-400 dark:text-neutral-500 italic">
 57                  (unset)
 58                </span>
 59              ) : (
 60                value
 61              )}
 62            </td>
 63          </tr>
 64        ))}
 65      </tbody>
 66    </table>
 67  );
 68}
 69
 070export default function DebugConfigRoute({ loaderData }: Route.ComponentProps) {
 071  const importMetaEnv = pickImportMetaEnvForDebug();
 072  const windowPublic = readPublicRuntimeConfigFromWindow();
 073  const apiBaseClient = getApiBase();
 74
 075  return (
 76    <main className="pt-16 p-4 container mx-auto max-w-4xl space-y-10">
 77      <header>
 78        <h1 className="text-2xl font-semibold tracking-tight">Debug configuration</h1>
 79        <p className="mt-2 text-neutral-600 dark:text-neutral-400 text-sm">
 80          Gated by{" "}
 81          <code className="text-xs bg-neutral-100 dark:bg-neutral-800 px-1 rounded">
 82            import.meta.env.DEV
 83          </code>{" "}
 84          or{" "}
 85          <code className="text-xs bg-neutral-100 dark:bg-neutral-800 px-1 rounded">
 86            ENABLE_DEBUG_CONFIG=true
 87          </code>
 88          {". Only non-secret keys are listed; do not expose this URL publicly in production."}
 89        </p>
 90      </header>
 91
 92      <section className="space-y-3">
 93        <h2 className="text-lg font-medium">Build (baked at image build)</h2>
 94        <dl className="grid gap-2 text-sm font-mono">
 95          <div className="flex flex-wrap gap-x-2 gap-y-1">
 96            <dt className="text-neutral-500 shrink-0">VITE_APP_VERSION</dt>
 97            <dd className="break-all">
 98              {import.meta.env.VITE_APP_VERSION || (
 99                <span className="text-neutral-400 dark:text-neutral-500 italic">
 100                  (unset)
 101                </span>
 102              )}
 103            </dd>
 104          </div>
 105          <div className="flex flex-wrap gap-x-2 gap-y-1">
 106            <dt className="text-neutral-500 shrink-0">VITE_GIT_SHA</dt>
 107            <dd className="break-all">
 108              {import.meta.env.VITE_GIT_SHA || (
 109                <span className="text-neutral-400 dark:text-neutral-500 italic">
 110                  (unset)
 111                </span>
 112              )}
 113            </dd>
 114          </div>
 115        </dl>
 116      </section>
 117
 118      <section className="space-y-3">
 119        <h2 className="text-lg font-medium">API base (effective)</h2>
 120        <dl className="grid gap-2 text-sm font-mono">
 121          <div className="flex flex-wrap gap-x-2 gap-y-1">
 122            <dt className="text-neutral-500 shrink-0">SSR / loader</dt>
 123            <dd className="break-all">{loaderData.apiBaseResolvedOnServer || "(empty)"}</dd>
 124          </div>
 125          <div className="flex flex-wrap gap-x-2 gap-y-1">
 126            <dt className="text-neutral-500 shrink-0">This browser</dt>
 127            <dd className="break-all">{apiBaseClient || "(empty)"}</dd>
 128          </div>
 129        </dl>
 130      </section>
 131
 132      <section className="space-y-3">
 133        <h2 className="text-lg font-medium">Public runtime (window)</h2>
 134        <p className="text-sm text-neutral-600 dark:text-neutral-400">
 135          From root loader → <code>window.__CLUTTERSTOCK_PUBLIC__</code> (browser OTEL, etc.).
 136        </p>
 137        <EnvTable
 138          rows={{
 139            otelTracesEndpoint: windowPublic?.otelTracesEndpoint ?? "",
 140            otelServiceName: windowPublic?.otelServiceName ?? "",
 141          }}
 142        />
 143      </section>
 144
 145      <section className="space-y-3">
 146        <h2 className="text-lg font-medium">Server env (allowlisted)</h2>
 147        <p className="text-sm text-neutral-600 dark:text-neutral-400">
 148          Snapshot from Node when the loader ran. OTEL SDK also reads other standard{" "}
 149          <code className="text-xs">OTEL_*</code> variables not listed here.
 150        </p>
 151        <EnvTable rows={loaderData.serverEnv} />
 152      </section>
 153
 154      <section className="space-y-3">
 155        <h2 className="text-lg font-medium">import.meta.env (client bundle)</h2>
 156        <p className="text-sm text-neutral-600 dark:text-neutral-400">
 157          Vite-inlined at build time; useful for local and image build diagnosis.
 158        </p>
 159        <EnvTable rows={importMetaEnv} />
 160      </section>
 161    </main>
 162  );
 163}