Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supabase functions serve: Import maps fail to resolve inside of 'functions' directory #1338

Closed
ChuckJonas opened this issue Jul 27, 2023 · 8 comments · Fixed by #2187
Closed
Assignees

Comments

@ChuckJonas
Copy link

ChuckJonas commented Jul 27, 2023

Issue

It seems like import maps are failing in multiple ways:

  1. When the mapped directory is INSIDE the function folder, the import map does not properly resolve in the docker instance
  2. When the import is outside of the supabase folder, it seems like a private module is created? But this causes the Duplicate mount point issue
  3. Behavior of import maps seems to be different if --import-maps flag vs using the defaults

Note: I haven't had a chance to test any of this with deploy, but I assume these issues will carry over in one way or another...

Reproduction

(this was previously posted to #1093, but decided it deserves a new, open issue)

This is failing in my setup:

Project Structure

root
   - common
   - react-app
   - supabase
   - functions
      - _core
         - supabaseClient.ts
      - chat
         - index.ts
      - import_map.json
   - package.json

supabase/functions/chat/index.ts

import { corsHeaders } from "core/supabaseClient.ts";
import { fnSharedWithReact } from "common/template";

In "supabase_edge_runtime" Docker container

home/deno

home/deno
  - fallback_import_map.json
  - main
  - functions
     - _core
        - supabaseClient.ts
     - chat
        - index.ts
     - import_map.json
  - modules
      - 4b0ed4fd36b0064d333d0ebb53b49ba5d84e9b130af0ab0c15f9924364d718c6

fallback_import_map.json

{
    "imports": {
        "@supabase/supabase-js": "https://esm.sh/@supabase/supabase-js@2",
        "common/": "/home/deno/modules/4b0ed4fd36b0064d333d0ebb53b49ba5d84e9b130af0ab0c15f9924364d718c6/",
        "core/": "./_core/"
    },
    "scopes": {}
}

The deno LSP (vscode) is happy with this configuration, but when I try to invoke the functions/chat function, I get this error:

Failed to load module: "file:///home/deno/_core/supabaseClient.ts" - No such file or directory (os error 2)

It seems like thefallback_import_map.json that gets setup in the "supabase_edge_runtime" container is referencing the wrong path:

"core/": "./_core/" should be "core/": "./functions/_core/"

Also, when I try to run it with the --import-map flag, I get the Duplicate mount point error as above:

supabase functions serve --env-file .env --no-verify-jwt --import-map supabase/functions/import_map.json

-> Error response from daemon: Duplicate mount point: /home/deno/modules/4b0ed4fd36b0064d333d0ebb53b49ba5d84e9b130af0ab0c15f9924364d718c6

Update

If I update my import map to:

    "core/": "./functions/_core/",

Then it works (as suspected), but this breaks the imports in my local deno LSP... Also, it goes against what was said in #1093:

paths in import_map are relative to supabase/functions directory

So... I don't really understand what's going on.

My workaround was to move my import map OUTSIDE of functions (./supabase/import-map.json), and now vscode and supabase serve are at least consistent. However, when I do this, it doesn't even attempt to generate the module for common anymore.

@idudinov
Copy link

idudinov commented Aug 4, 2023

Hi! Currently I abandoned using import maps (aka path aliases) within functions folder and moved all my client-server re-usable code outside supabase folder, and it works perfectly both in local and deployed versions.

However, since using relative paths is evil, I'm also looking for a solution for this issue to be able to use backend-only aliases for functions.

I suppose it could be resolved by keeping the same folders structure as in the project folder, I mean avoid moving import_map.json from supabase/functions to supabase level and mount /supabase/functions (instead of just functions) without any extra stuff like migrations etc., so in such case relative mappings in import_map.json shouldn't break I think. (or maybe re-map them by adding ./functions prefix?)

@rasphlat
Copy link

rasphlat commented Aug 9, 2023

In my case this issue occurs only on Windows, on MacOS is working fine

@laktek laktek self-assigned this Aug 10, 2023
@Matx00
Copy link

Matx00 commented Aug 18, 2023

@idudinov Hi, could you provide an example of how you structured the file? I tried what you said but still getting errors.
Thank you!

@idudinov
Copy link

idudinov commented Sep 5, 2023

@Matx00 no problem, here's my setup.

// supabase/functions/import_map.json

{
    "imports": {
        // here listed all packages that are used in "common"
        "yup": "https://esm.sh/yup@1.2.0",

        // the "common" folder is in the root dir
        "common/": "../../src/common/"
    }
}

Now I can reference my models from common in Deno files:

import { UserProfile } from 'common/types/models/index.ts';

However I still use relative paths for my shared code within functions:

import '../_shared/utils/bigint.ts';

Hopefully this helps, but don't hesitate to ask any questions if any.

@ChuckJonas ChuckJonas changed the title supabase functions serve: Import maps failing to resolve proper directory & volume issue with modules supabase functions serve: Import maps fail to resolve inside of 'functions' directory Sep 25, 2023
@ChuckJonas
Copy link
Author

@laktek based on the comments here and additional research in my own project, I think the scope of this issue can be defined using the following reproduction steps.

Reproduction Steps

  1. Create a new supabase project
  2. create a new file supabase/functions/_shared/foo.ts with the following:
export const foo = 'bar'
  1. create a file supabase/functions/import_map.json with the following:
    "shared/": "./_shared/"
  1. create a new supabase function with the following:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { foo } from 'shared/foo.ts'; 

console.log("Hello from Functions!")

serve(async (req) => {
  console.log(foo);
  const { name } = await req.json()
  const data = {
    message: `Hello ${name}!`,
  }

  return new Response(
    JSON.stringify(data),
    { headers: { "Content-Type": "application/json" } },
  )
})
  1. run the function:serve locally and curl the created function. You should see an error similar to this one:
Failed to load module: "file:///home/deno/_shared/foo.ts" - No such file or directory (os error 2)
An error has occured
InvalidWorkerCreation: worker boot error
    at async Function.create (ext:sb_user_workers/user_workers.js:124:15)
    at async Server.<anonymous> (file:///home/deno/main/index.ts:110:20)
    at async Server.#respond (https://deno.land/std@0.182.0/http/server.ts:220:18) {
  name: "InvalidWorkerCreation"
}

Expected Result

The module should be resolving to file:///home/deno/functions/_shared/foo.ts

Workaround

Move supabase/functions/_shared to supabase/_shared and update import_map.json.

Other Notes

The fix might be to update the bindImportMap function to detect imports inside of the functions directory (./) and properly rewrite these paths to ./functions.

@evelant
Copy link

evelant commented Dec 4, 2023

@sweatybridge have you had a chance to look at this? It seems to boil down to the cli mounting the import map in the container at /home/deno when it should be in /home/deno/functions so that relative paths remain correct since the default placement of import_map.json is supabase/functions in a project.

@inorganik
Copy link

inorganik commented Feb 3, 2024

I was struggling with trying to get import_map.json to work, only to discover that since v1.30, Deno wants you to put import aliases in the imports object of deno.json.

Since version 1.30, the deno.json configuration file acts as an import map for resolving bare specifiers.

See https://docs.deno.com/runtime/manual/getting_started/configuration_file#imports-and-scopes

Update: This makes my IDE happy but I hit a runtime error - "Relative import path "..." not prefixed with / or ./ or ../"...

Update 2: The error only occurs for executable code, it works fine for importing models

@sweatybridge
Copy link
Contributor

I finally managed to look into this more. I had to use absolute path when mounting import map inside the container.

Feel free to verify this fix with npx supabase@beta functions serve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants