sst / ion

❍ — a new engine for SST
https://ion.sst.dev
MIT License
888 stars 78 forks source link

CF Worker No such module error using Drizzle & Libsql #357

Open jluisrojas opened 2 weeks ago

jluisrojas commented 2 weeks ago

When deploying or running sst dev with a worker that uses Dirzzle and libsql the following error happens:

|  Error: No such module "node:http".
|  imported from "worker.mjs"
|  (10021)

×  Failed
   Hono sst:cloudflare:Worker → HonoScript cloudflare:index:WorkerScript
   updating urn:pulumi:joseluisrojasaranda::honolibsql::sst:cloudflare:Worker$cloudflare:index/workerScript:WorkerScript::HonoScript: 1 error occurred:

   Error: No such module "node:http".
   imported from "worker.mjs"
   (10021)

If I use wrangler it works fine, so i believe is something related to how esbuild bundles the edge runtime

The worker code looks as follows:

import { Hono } from "hono";
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client/web";

const app = new Hono().get("*", async (c) => {
  const url = "";
  const authToken = "";

  const client = createClient({
    url,
    authToken,
  });

  const db = drizzle(client);

  return c.text("Hello");
});

export default app;

sst.config.ts

export default $config({
  app(input) {
    return {
      name: "honolibsql",
      removal: input?.stage === "production" ? "retain" : "remove",
      home: "cloudflare",
    };
  },
  async run() {
    const hono = new sst.cloudflare.Worker("Hono", {
      url: true,
      handler: "index.ts",
    });

    return {
      api: hono.url,
    };
  },
});

I made the following repo if you guys want to replicate it:

https://github.com/jluisrojas/ion-libsql

Ernxst commented 2 weeks ago

This isn't an SST issue - The @libsql/client/web imports some code which depends onnode:http which esbuild doesn't handle well. What worked for me, somehow, was setting the platform option in the esbuild config to browser:

const hono = new sst.cloudflare.Worker("Hono", {
  url: true,
  handler: "index.ts",
  build: {
    esbuild: {
      platform: 'browser'
    }
  }
});

In my case, I was only using packages built for edge functions so setting this wasn't a big deal - your mileage may vary.

jayair commented 2 weeks ago

@thdxr does it make sense to default workers to bundling for the browser?

jluisrojas commented 2 weeks ago

If I set the worker as @Ernxst indicates

const hono = new sst.cloudflare.Worker("Hono", {
  url: true,
  handler: "index.ts",
  build: {
    esbuild: {
      platform: 'browser'
    }
  }
});

I now get the following error

Could not resolve "node:process"
1 │ import { env } from "node:process";
|  Error        Error:
|  ../../../node_modules/.pnpm/sst@3.0.13/node_modules/sst/dist/resource.js
|
|  at file:///Users/joseluisrojasaranda/hono-libsql/.sst/platform/src/components/cloudflare/worker.ts:372:17
|  at processTicksAndRejections (node:internal/process/task_queues:95:5) {
|  promise: Promise { <rejected> [Circular *1] }
|  }

The error is similar, but now "node:process" instead of "node:http"

Ernxst commented 2 weeks ago

You then also need to add external: ['node:process'] to the esbuild config. What I usually do is externalise every builtin module so I don't run into this:

import { builtinModules } from "node:module";

... rest of config
   external: [
   // Target both with and without the node protocol
  ...builtinModules,
  ...builtinModules.map((m) => `node:${m}`),
]

I do this whenever I use esbuild, even outside of sst.

ruchernchong commented 1 week ago

I have this similar problem too. I believe is Cloudflare Workers not supporting these modules rather than an SST problem.

@Ernxst I was using it with a MongoDB npm package which has some node:* dependencies. Do I put the MongoDB package into what you have suggested too?

Ernxst commented 1 week ago

I don't think you should - you still want the module bundled, just not the node modules it depends on. If you try this I'd expect to see a module not found error for your MongoDB lib - it's probably better to confirm whether the lib supports edge runtimes beforehand