Browse Source

chore: debug changelog

adamelmore 3 weeks ago
parent
commit
b0f865eae5

+ 29 - 4
packages/console/app/src/routes/changelog.json.ts

@@ -104,7 +104,12 @@ export async function GET() {
       cacheTtl: 60 * 5,
       cacheTtl: 60 * 5,
       cacheEverything: true,
       cacheEverything: true,
     },
     },
-  } as any).catch(() => undefined)
+  } as any).catch((err) => {
+    console.error("[changelog.json] fetch failed", {
+      error: err instanceof Error ? err.message : String(err),
+    })
+    return undefined
+  })
 
 
   const fail = () =>
   const fail = () =>
     new Response(JSON.stringify({ releases: [] }), {
     new Response(JSON.stringify({ releases: [] }), {
@@ -116,10 +121,30 @@ export async function GET() {
       },
       },
     })
     })
 
 
-  if (!response?.ok) return fail()
+  if (!response) return fail()
+  if (!response.ok) {
+    const body = await response.text().catch(() => undefined)
+    console.error("[changelog.json] github non-ok", {
+      status: response.status,
+      remaining: response.headers.get("x-ratelimit-remaining"),
+      reset: response.headers.get("x-ratelimit-reset"),
+      body: body?.slice(0, 300),
+    })
+    return fail()
+  }
 
 
-  const data = await response.json().catch(() => undefined)
-  if (!Array.isArray(data)) return fail()
+  const data = await response.json().catch((err) => {
+    console.error("[changelog.json] json parse failed", {
+      error: err instanceof Error ? err.message : String(err),
+    })
+    return undefined
+  })
+  if (!Array.isArray(data)) {
+    console.error("[changelog.json] invalid json", {
+      type: typeof data,
+    })
+    return fail()
+  }
 
 
   const releases = data as Release[]
   const releases = data as Release[]
 
 

+ 107 - 8
packages/console/app/src/routes/changelog/index.tsx

@@ -1,11 +1,11 @@
 import "./index.css"
 import "./index.css"
 import { Title, Meta, Link } from "@solidjs/meta"
 import { Title, Meta, Link } from "@solidjs/meta"
-import { createAsync } from "@solidjs/router"
+import { createAsync, useSearchParams } from "@solidjs/router"
 import { Header } from "~/component/header"
 import { Header } from "~/component/header"
 import { Footer } from "~/component/footer"
 import { Footer } from "~/component/footer"
 import { Legal } from "~/component/legal"
 import { Legal } from "~/component/legal"
 import { config } from "~/config"
 import { config } from "~/config"
-import { For, Show, createSignal } from "solid-js"
+import { For, Show, createSignal, onMount } from "solid-js"
 import { getRequestEvent } from "solid-js/web"
 import { getRequestEvent } from "solid-js/web"
 
 
 type HighlightMedia = { type: "video"; src: string } | { type: "image"; src: string; width: string; height: string }
 type HighlightMedia = { type: "video"; src: string } | { type: "image"; src: string; width: string; height: string }
@@ -31,6 +31,21 @@ type ChangelogRelease = {
   sections: { title: string; items: string[] }[]
   sections: { title: string; items: string[] }[]
 }
 }
 
 
+type LoadMeta = {
+  endpoint: string
+  ssr: boolean
+  hasEvent: boolean
+  ok: boolean
+  status?: number
+  contentType?: string
+  error?: string
+}
+
+type Load = {
+  releases: ChangelogRelease[]
+  meta: LoadMeta
+}
+
 function endpoint() {
 function endpoint() {
   const event = getRequestEvent()
   const event = getRequestEvent()
   if (event) return new URL("/changelog.json", event.request.url).toString()
   if (event) return new URL("/changelog.json", event.request.url).toString()
@@ -38,12 +53,64 @@ function endpoint() {
   return `${config.baseUrl}/changelog.json`
   return `${config.baseUrl}/changelog.json`
 }
 }
 
 
-async function getReleases() {
-  const response = await fetch(endpoint()).catch(() => undefined)
-  if (!response?.ok) return []
+async function getReleases(debug = false): Promise<Load> {
+  const url = endpoint()
+  const meta = {
+    endpoint: url,
+    ssr: import.meta.env.SSR,
+    hasEvent: Boolean(getRequestEvent()),
+    ok: false,
+  } satisfies LoadMeta
+
+  const response = await fetch(url).catch((err) => {
+    console.error("[changelog] fetch failed", {
+      ...meta,
+      error: err instanceof Error ? err.message : String(err),
+    })
+    return undefined
+  })
+
+  if (!response) return { releases: [], meta: { ...meta, error: "fetch_failed" } }
+  if (!response.ok) {
+    const contentType = response.headers.get("content-type") ?? undefined
+    const body = debug ? await response.text().catch(() => undefined) : undefined
+    console.error("[changelog] fetch non-ok", {
+      ...meta,
+      status: response.status,
+      contentType,
+      body: body?.slice(0, 300),
+    })
+    return { releases: [], meta: { ...meta, status: response.status, contentType, error: "bad_status" } }
+  }
+
+  const contentType = response.headers.get("content-type") ?? undefined
+  const copy = debug ? response.clone() : undefined
+  const json = await response.json().catch(async (err) => {
+    const body = copy ? await copy.text().catch(() => undefined) : undefined
+    console.error("[changelog] json parse failed", {
+      ...meta,
+      status: response.status,
+      contentType,
+      error: err instanceof Error ? err.message : String(err),
+      body: body?.slice(0, 300),
+    })
+    return undefined
+  })
+
+  const releases = Array.isArray(json?.releases) ? (json.releases as ChangelogRelease[]) : []
+  if (!releases.length) {
+    console.error("[changelog] empty releases", {
+      ...meta,
+      status: response.status,
+      contentType,
+      keys: json && typeof json === "object" ? Object.keys(json) : undefined,
+    })
+  }
 
 
-  const json = await response.json().catch(() => undefined)
-  return Array.isArray(json?.releases) ? (json.releases as ChangelogRelease[]) : []
+  return {
+    releases,
+    meta: { ...meta, ok: true, status: response.status, contentType },
+  }
 }
 }
 
 
 function formatDate(dateString: string) {
 function formatDate(dateString: string) {
@@ -134,7 +201,22 @@ function CollapsibleSections(props: { sections: { title: string; items: string[]
 }
 }
 
 
 export default function Changelog() {
 export default function Changelog() {
-  const releases = createAsync(() => getReleases())
+  const [params] = useSearchParams()
+  const debug = () => params.debug === "1"
+  const data = createAsync(() => getReleases(debug()))
+  const [client, setClient] = createSignal<Load | undefined>(undefined)
+  const releases = () => client()?.releases ?? data()?.releases ?? []
+
+  onMount(() => {
+    queueMicrotask(async () => {
+      const server = data()?.releases
+      if (!server) return
+      if (server.length) return
+
+      const next = await getReleases(debug())
+      setClient(next)
+    })
+  })
 
 
   return (
   return (
     <main data-page="changelog">
     <main data-page="changelog">
@@ -152,6 +234,23 @@ export default function Changelog() {
           </section>
           </section>
 
 
           <section data-component="releases">
           <section data-component="releases">
+            <Show when={releases().length === 0}>
+              <p>
+                No changelog entries found. <a href="/changelog.json">View JSON</a>
+              </p>
+            </Show>
+            <Show when={debug()}>
+              <pre style={{ "font-size": "12px", "line-height": "1.4", padding: "12px" }}>
+                {JSON.stringify(
+                  {
+                    server: data()?.meta,
+                    client: client()?.meta,
+                  },
+                  null,
+                  2,
+                )}
+              </pre>
+            </Show>
             <For each={releases()}>
             <For each={releases()}>
               {(release) => {
               {(release) => {
                 return (
                 return (