From 6c0f1f304077dceee052646426b35bd3a86a1270 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 18:21:31 +0000 Subject: [PATCH] The remaining runtime fetches retry, except the one where a miss is the plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The follow-up dx-shepherd queued: wire retryFetch into the library fetches with no failure handling, and skip any that handle failure deliberately. Four qualified, one did not, and the distinction is the work. WIRED, because each already handles an HTTP error and NOT a transport one: usePosterPrints the poster HTML — checks .ok, so a 404 is deliberate; a network throw went uncaught and the poster simply failed useSharedMapToken the token service — its .catch degrades to '' by design, but the result is MEMOISED one-fetch-per-URL-per-page, so a single blip meant no token for the whole page and a tokenless Mapbox map useCsvExport the bulk list — .ok checked, transport throw blanks the export PeopleGroupDetail the detail API — .ok checked, transport throw blanks the panel In every one the deliberate degradation is unchanged; it now simply survives a blip first. retryFetch returns a non-ok RESPONSE untouched, so no .ok path moves. NOT WIRED, and named in the gate rather than silently skipped: usePosterPrints' probe for an OPTIONAL pre-rendered .webp. A miss is the EXPECTED path there — it falls through to generating the poster — so retrying would delay the fallback three times over for an asset that is legitimately absent. That is failure handling that means something, which is exactly what the instruction said to leave alone. The gate now covers all eight sites and carries the exemption as a COUNT for that one file, so a second bare fetch appearing there still fails. Negative-tested: reverting any wired site to bare fetch turns it red. --- internal/check-retry-fetch.mjs | 17 ++++++++++++++--- library/components/PeopleGroupDetail.vue | 3 ++- library/composables/useCsvExport.js | 3 ++- library/composables/usePosterPrints.js | 3 ++- library/composables/useSharedMapToken.js | 3 ++- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/internal/check-retry-fetch.mjs b/internal/check-retry-fetch.mjs index 57c1b5843..b89d8d52c 100644 --- a/internal/check-retry-fetch.mjs +++ b/internal/check-retry-fetch.mjs @@ -67,16 +67,27 @@ const realFetch = globalThis.fetch globalThis.fetch = realFetch // ── and the shared data paths actually use it ──────────────────────────────────────────────────── +// ★ ONE SITE IS DELIBERATELY EXEMPT AND IS NAMED, not silently skipped. usePosterPrints probes for an +// OPTIONAL pre-rendered .webp and falls through to generating the poster when it is absent — a miss is +// the expected path, so retrying would delay the fallback for an asset that is legitimately not there. +// Everything else in that file, and every other runtime request, must retry. +const EXEMPT = new Map([['library/composables/usePosterPrints.js', 1]]) for (const rel of [ 'library/composables/useMapLayers.js', 'library/composables/useCountryOutline.js', 'library/lists/peopleGroupList.js', 'library/composables/usePrayerStatistics.js', + 'library/composables/usePosterPrints.js', + 'library/composables/useSharedMapToken.js', + 'library/composables/useCsvExport.js', + 'library/components/PeopleGroupDetail.vue', ]) { const src = readFileSync(join(ROOT, rel), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '') - if (/(? allowed) { + fails.push(`${rel} has ${bare} bare fetch() call(s) for a runtime request, ${allowed} allowed — a transport\n` + + ' blip there leaves the feature silently absent. Use retryFetch().') } } diff --git a/library/components/PeopleGroupDetail.vue b/library/components/PeopleGroupDetail.vue index 611b695b4..62e9e2328 100644 --- a/library/components/PeopleGroupDetail.vue +++ b/library/components/PeopleGroupDetail.vue @@ -108,6 +108,7 @@