jstack icon indicating copy to clipboard operation
jstack copied to clipboard

Jstack and Better Auth ENV problem

Open emretfn opened this issue 10 months ago • 13 comments

Using jstack & better-auth in a Cloudflare Workers Environment

Hi,

I'm encountering some issues while trying to use better-auth with jstack. Below, I've detailed the steps I took and the problems I faced, particularly regarding accessing environment variables in the Cloudflare Workers environment where process.env is not available. I'm looking for guidance on how to integrate jstack and better-auth under these constraints.

1. Creating the db Object with Drizzle

First, in the src/lib/db.ts file, I created a db object using Drizzle:

import { drizzle } from "drizzle-orm/neon-http";

const getDbUrl = () => {
  if (typeof process.env.DATABASE_URL === "undefined") {
    throw new Error("DATABASE_URL is not defined");
  }

  return process.env.DATABASE_URL;
};

export const db = drizzle(getDbUrl());

2. Using the Drizzle Adapter for better-auth

In the src/lib/auth.ts file, I passed the drizzle adapter along with the necessary schemas to the better-auth function:

import { betterAuth } from "better-auth";
import { db } from "./db";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { posts } from "@/server/db/schema";
import { account, session, user, verification } from "../../auth-schema";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      ...posts,
      user: user,
      account: account,
      session: session,
      verification: verification,
    },
  }),
  emailAndPassword: {
    enabled: true,
  },
});

3. Defining the API Route Handler

I defined the handler from the returned auth object as the route handler for POST and GET requests in src/server/index.ts:

const api = j
  .router()
  .basePath("/api")
  .on(["POST", "GET"], "/auth/**", (c) => auth.handler(c.req.raw))
  .use(j.defaults.cors)
  .onError(j.defaults.errorHandler);

4. Setting Up the Auth Middleware

In the src/server/jstack.ts file, I defined an auth middleware that also makes use of the auth object:

// ... other code
const databaseMiddleware = j.middleware(async ({ c, next }) => {
  const { DATABASE_URL } = env(c);

  const db = drizzle(DATABASE_URL);

  return await next({ db });
});

const authMiddleware = j.middleware(async ({ c, next }) => {
  const session = await auth.api.getSession({ headers: c.req.raw.headers });

  if (!session) {
    throw new HTTPException(401, {
      message: "Unauthorized",
    });
  }

  return await next({ user: session.user });
});

// ... other code
export const privateProcedure = j.procedure.use(databaseMiddleware).use(authMiddleware);

5. Wrangler Configuration

While deploying to Cloudflare Workers, I initially encountered errors that were resolved by adding the compatibility_flags and updating the compatibility_date in my wrangler.toml file:

name = "app-name"
compatibility_flags = [ "nodejs_compat" ]
compatibility_date = "2024-09-23"
main = "src/server/index.ts"

[dev]
port = 8080

6. The Issue and Question

After the above steps, I began receiving an error in the src/lib/db.ts file because the Cloudflare Workers environment doesn't support accessing process.env.DATABASE_URL. Since Cloudflare Workers doesn't have the typical Node.js environment variables, they are instead provided via Workers bindings.

Question:
How should I access environment variables in a Cloudflare Workers environment when using jstack and better-auth together, instead of relying on process.env? What is the best practice in this situation? For instance, how can I structure the Workers bindings and integrate the drizzle adapter with better-auth in this context?

I'd appreciate any suggestions or recommendations on how to properly set up jstack and better-auth in a Cloudflare Workers environment.

Thanks!

emretfn avatar Feb 03 '25 19:02 emretfn