fix: resolve npm: supabase-js specifier for offline edge-runtime image - #517
Merged
Merged
Conversation
PR #513 switched edge functions from the esm.sh specifier to npm:@supabase/supabase-js@2.95.3, but docker/deno.json only remapped the esm.sh URL and the bare specifier. The npm: specifier fell through to a live registry fetch, which the offline edge-runtime container can't do, so every edge function request failed with a 500 (exchange-desktop-token and github-webhook CI checks failing).
Edge functions already import @supabase/supabase-js via its npm: specifier. Instead of bundling it into a single ESM file with Node + esbuild and remapping imports through deno.json, pre-warm Deno's own npm cache (DENO_DIR) for the pinned version in a `deno cache` build stage and ship that cache directly. No node_modules, no bundling step, no import-map remapping. deno.json now only pins nodeModulesDir to "none" so the shipped image never falls back to a local node_modules directory.
Ziinc
commented
Sep 23, 2026
Collaborator
Author
There was a problem hiding this comment.
Replaced the vendor stage (Node + esbuild bundling @supabase/supabase-js into a single .mjs) with an npm-cache stage that runs deno cache against the pinned npm:@supabase/supabase-js@2.95.3 specifier.
- The functions already import via
npm:...(feat: implementation of sprites, update to use npm: #513); the vendor bundle's import-map remap only covered the oldesm.shURL, so every function call was hitting a live registry fetch at runtime and failing with 500 — this is the actual CI fix. DENO_DIRis a stable Deno cache format, so warming it with the plaindenoCLI and copying it into the image (sameDENO_DIRpath edge-runtime already uses) is compatible without needing edge-runtime itself at build time.- No
node_modules, no esbuild, one fewer toolchain in the build.
Generated by Claude Code
Collaborator
Author
There was a problem hiding this comment.
Dropped the imports remap entirely — no code imports the bare @supabase/supabase-js or esm.sh specifiers anymore, so there was nothing left to remap.
"nodeModulesDir": "none"is the important part: this file is copied overfunctions/deno.json(which setsnodeModulesDir: "auto"for local dev), so without this override the image would fall back to creating a localnode_modules— exactly what pre-warmingDENO_DIRis meant to avoid.
Generated by Claude Code
Remove the deno-cache build stage; @supabase/supabase-js now resolves purely via its npm: specifier when edge-runtime loads a function, same as any other npm: import. No pre-warming, no vendoring.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Supabase Dockerworkflow,single-tenant self-hosted imagejob) was failing:exchange-desktop-tokenandgithub-webhookedge functions returned 500 for every request instead of proper 400/401 validation responses.npm:@supabase/supabase-js@2.95.3, but the offline fat image only remapped the oldesm.shspecifier to a vendored bundle. Thenpm:specifier fell through to a live registry fetch, which the offline edge-runtime container can't do, so every function invocation threw.DENO_DIR) for the pinned@supabase/supabase-jsversion viadeno cache, and that cache is shipped directly in the image. Nonode_modules, no bundling step, no import-map remapping — functions resolve theirnpm:import from disk like they would with a normal Deno cache.Changes
supabase/docker/Dockerfile: removed the Node+esbuildvendorstage; added annpm-cachestage (denoland/deno:alpine-2.1.4) that runsdeno cacheand copies the resultingDENO_DIRinto the final image.supabase/docker/deno.json: dropped the import-map remapping; now only pins"nodeModulesDir": "none"so the shipped image never falls back to a localnode_modulesdirectory.supabase/docker/openrc/run-edge-runtime.sh,README.md,versions.env: updated comments/docs to match.Test plan
npm-cachebuild stage in isolation (docker build --target npm-cache): correctly resolves and caches@supabase/supabase-js@2.95.3and its full dependency tree.docker buildof the fat image could not be completed in the dev sandbox (unrelated pre-existing Alpine/apk TLS limitation in that sandbox, reproduced against a barealpine:3.23image too) — needs confirmation from the real CI run, which doesn't have that constraint.supabase/docker/test/verify-self-hosted.sh(exchange-desktop-token/github-webhookchecks) should be re-verified green in CI.🤖 Generated with Claude Code
https://claude.ai/code/session_01T81HxmDYzHnYp5kg24ByLX
Generated by Claude Code