From fef419f572dd804f997f672ec7e663f7040b6911 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 2 Mar 2026 23:36:15 -0800 Subject: [PATCH] fix: folk-wrapper crash, service worker API exclusion, fal.ai endpoint - folk-wrapper: createRenderRoot crashed because innerHTML="" removed the slot from DOM, making parentElement null on the next line. Save parent ref before clearing. - sw.ts: module API paths (/space/module/api/...) weren't excluded from caching. Changed startsWith("/api/") to includes("/api/"). Also fixed catch handler returning undefined instead of a Response. - image-gen: changed queue.fal.run to fal.run for synchronous responses. The queue endpoint returns request_id, not the actual image data. Co-Authored-By: Claude Opus 4.6 --- lib/folk-wrapper.ts | 9 +++++---- server/index.ts | 6 +++--- website/sw.ts | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/folk-wrapper.ts b/lib/folk-wrapper.ts index 4cdc5bb..3edaa36 100644 --- a/lib/folk-wrapper.ts +++ b/lib/folk-wrapper.ts @@ -292,11 +292,12 @@ export class FolkWrapper extends FolkShape {
`; - // Replace existing content structure + // Replace existing content structure — save parent ref before clearing const existingSlot = root.querySelector("slot"); - if (existingSlot?.parentElement) { - existingSlot.parentElement.innerHTML = ""; - existingSlot.parentElement.appendChild(wrapper); + const slotParent = existingSlot?.parentElement; + if (slotParent) { + slotParent.innerHTML = ""; + slotParent.appendChild(wrapper); } // Get references diff --git a/server/index.ts b/server/index.ts index eb7bf3e..1178fa2 100644 --- a/server/index.ts +++ b/server/index.ts @@ -533,7 +533,7 @@ app.post("/api/image-gen", async (c) => { }; const styledPrompt = (stylePrompts[style] || "") + prompt; - const res = await fetch("https://queue.fal.run/fal-ai/flux-pro/v1.1", { + const res = await fetch("https://fal.run/fal-ai/flux-pro/v1.1", { method: "POST", headers: { Authorization: `Key ${FAL_KEY}`, @@ -567,7 +567,7 @@ app.post("/api/video-gen/t2v", async (c) => { const { prompt, duration } = await c.req.json(); if (!prompt) return c.json({ error: "prompt required" }, 400); - const res = await fetch("https://queue.fal.run/fal-ai/wan/v2.1", { + const res = await fetch("https://fal.run/fal-ai/wan/v2.1", { method: "POST", headers: { Authorization: `Key ${FAL_KEY}`, @@ -600,7 +600,7 @@ app.post("/api/video-gen/i2v", async (c) => { const { image, prompt, duration } = await c.req.json(); if (!image) return c.json({ error: "image required" }, 400); - const res = await fetch("https://queue.fal.run/fal-ai/kling-video/v1/standard/image-to-video", { + const res = await fetch("https://fal.run/fal-ai/kling-video/v1/standard/image-to-video", { method: "POST", headers: { Authorization: `Key ${FAL_KEY}`, diff --git a/website/sw.ts b/website/sw.ts index e20893d..d0f3eaa 100644 --- a/website/sw.ts +++ b/website/sw.ts @@ -40,12 +40,12 @@ self.addEventListener("fetch", (event) => { // Skip non-http(s) schemes (chrome-extension://, etc.) — they can't be cached if (!url.protocol.startsWith("http")) return; - // Skip WebSocket and API requests entirely + // Skip WebSocket and API requests entirely (including module APIs like /space/module/api/...) if ( event.request.url.startsWith("ws://") || event.request.url.startsWith("wss://") || url.pathname.startsWith("/ws/") || - url.pathname.startsWith("/api/") + url.pathname.includes("/api/") ) { return; } @@ -101,7 +101,7 @@ self.addEventListener("fetch", (event) => { } return response; }) - .catch(() => cached as Response); + .catch(() => cached || new Response("Offline", { status: 503 })); return cached || fetchPromise; }) );