{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "use-region-ping",
  "title": "useRegionPing",
  "description": "Measures browser round-trip latency to per-region endpoints via opaque no-cors requests.",
  "files": [
    {
      "path": "src/hooks/use-region-ping.ts",
      "content": "\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport type RegionPingResult = number | null;\n\nexport type RegionPingStatus = \"idle\" | \"measuring\" | \"done\";\n\nexport interface UseRegionPingOptions {\n  /** Timed requests per region after the warmup; the best time wins. */\n  samples?: number;\n  /** Set false to defer measuring, then call refresh() when ready. */\n  enabled?: boolean;\n}\n\nconst DEFAULT_SAMPLES = 3;\n\n/** One opaque round-trip to the endpoint; null when unreachable. */\nconst timeRequest = async (url: string): Promise<RegionPingResult> => {\n  try {\n    const start = performance.now();\n\n    await fetch(url, {\n      cache: \"no-store\",\n      method: \"HEAD\",\n      mode: \"no-cors\",\n    });\n\n    return Math.round(performance.now() - start);\n  } catch {\n    return null;\n  }\n};\n\nconst measureRegion = async (\n  url: string,\n  samples: number\n): Promise<RegionPingResult> => {\n  // Warmup request pays DNS + TLS so samples measure the wire.\n  await timeRequest(url);\n\n  let best: RegionPingResult = null;\n\n  for (let index = 0; index < samples; index += 1) {\n    // Sequential on purpose: parallel samples contend for the socket.\n    // eslint-disable-next-line no-await-in-loop\n    const sample = await timeRequest(url);\n\n    if (sample !== null && (best === null || sample < best)) {\n      best = sample;\n    }\n  }\n\n  return best;\n};\n\n/**\n * Measures round-trip latency from the browser to each region\n * endpoint. Endpoints must tolerate opaque no-cors HEAD requests\n * (any reachable URL works; the response is never read).\n */\nexport const useRegionPing = (\n  urls: Record<string, string>,\n  { enabled = true, samples = DEFAULT_SAMPLES }: UseRegionPingOptions = {}\n) => {\n  const [pings, setPings] = useState<Record<string, RegionPingResult>>({});\n  const [status, setStatus] = useState<RegionPingStatus>(\"idle\");\n  const urlsRef = useRef(urls);\n\n  useEffect(() => {\n    urlsRef.current = urls;\n  }, [urls]);\n\n  const refresh = useCallback(async () => {\n    setStatus(\"measuring\");\n\n    const entries = Object.entries(urlsRef.current);\n\n    await Promise.all(\n      entries.map(async ([id, url]) => {\n        const ping = await measureRegion(url, samples);\n        setPings((current) => ({ ...current, [id]: ping }));\n      })\n    );\n\n    setStatus(\"done\");\n  }, [samples]);\n\n  useEffect(() => {\n    if (!enabled) {\n      return;\n    }\n\n    // Deferred a frame so the initial \"measuring\" state doesn't\n    // set state synchronously inside the effect body.\n    const frame = requestAnimationFrame(() => {\n      void refresh();\n    });\n\n    return () => cancelAnimationFrame(frame);\n  }, [enabled, refresh]);\n\n  return { pings, refresh, status };\n};\n",
      "type": "registry:hook"
    }
  ],
  "type": "registry:hook"
}