From 451c1fe74f38cd0ef4c5f8126fa1c66324563f5a Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Wed, 28 Oct 2026 12:02:26 -0400 Subject: [PATCH] viewer: storage origin follows the env, not the first stamp in the process A texture stamped before NEXT_PUBLIC_SUPABASE_URL is read (the native texture tests from #1190, run first on Linux) pinned a null origin, so later storage URLs resolved to no reference. Co-Authored-By: Claude Opus 5.5 --- .../viewer/src/lib/texture-reference.test.ts | 4 ++-- packages/viewer/src/lib/texture-reference.ts | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/viewer/src/lib/texture-reference.test.ts b/packages/viewer/src/lib/texture-reference.test.ts index bb45b6121c..0663047478 100644 --- a/packages/viewer/src/lib/texture-reference.test.ts +++ b/packages/viewer/src/lib/texture-reference.test.ts @@ -4,8 +4,8 @@ import { describe, expect, test } from 'bun:test' import * as THREE from 'three' import { getPascalTextureRef, stampPascalTextureRef } from './texture-reference' -// The module reads the storage origin lazily on first use, so setting the env -// here (before any stamp call) pins it for the whole test file. +// The module reads the storage origin from the env, so a stamp in another file +// run earlier in the process does not decide it for this one. process.env.NEXT_PUBLIC_SUPABASE_URL ??= 'https://test-storage.supabase.co' const STORAGE_ORIGIN = new URL(process.env.NEXT_PUBLIC_SUPABASE_URL).origin diff --git a/packages/viewer/src/lib/texture-reference.ts b/packages/viewer/src/lib/texture-reference.ts index a11cbbda7f..c2dd2ecf80 100644 --- a/packages/viewer/src/lib/texture-reference.ts +++ b/packages/viewer/src/lib/texture-reference.ts @@ -33,16 +33,18 @@ const STORAGE_BUCKET_BY_KIND = { 'project-asset': 'project-assets', } as const -let cachedStorageOrigin: string | null | undefined +// Keyed by the URL it was read from, so a texture stamped before the env is set never pins a +// null origin for the rest of the process. +let cachedStorageOrigin: { url: string | undefined; origin: string | null } | undefined function pascalStorageOrigin(): string | null { - if (cachedStorageOrigin !== undefined) return cachedStorageOrigin + const url = process.env.NEXT_PUBLIC_SUPABASE_URL + if (cachedStorageOrigin && cachedStorageOrigin.url === url) return cachedStorageOrigin.origin + let origin: string | null = null try { - const url = process.env.NEXT_PUBLIC_SUPABASE_URL - cachedStorageOrigin = url ? new URL(url).origin : null - } catch { - cachedStorageOrigin = null - } - return cachedStorageOrigin + origin = url ? new URL(url).origin : null + } catch {} + cachedStorageOrigin = { url, origin } + return origin } /** Static catalog materials ship in the app's public dir and resolve through