[GH-ISSUE #1272] Expose schema generators from the cli package #8667

Closed
opened 2026-04-13 03:49:26 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @Thomascogez on GitHub (Jan 23, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1272

Is this suited for github?

  • Yes, this is suited for github

Hey, I work on multiple project using cloudflare worker and better-auth.
By the cloudflare worker platform design, bindings (such as d1 database, secrets, ...) cannot be directly accessed.

In order make the process of running scripts that can access cloudflare binding I'm working on a project called cf-script .

I would like to add example scripts that will allow to make the generate and migrate command from better-auth work with cloudflare workers.

While better-auth/db expose methods such as getAuthTables, we don't have access to generator functions included inside better-auth/cli package that are necessary in order to reproduce the generate command

Describe the solution you'd like

Export generators functions from better-auth/cli package

Describe alternatives you've considered

N/A

Additional context

No response

Originally created by @Thomascogez on GitHub (Jan 23, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1272 ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. Hey, I work on multiple project using `cloudflare worker` and `better-auth`. By the cloudflare worker platform design, bindings (such as d1 database, secrets, ...) cannot be directly accessed. In order make the process of running scripts that can access cloudflare binding I'm working on a project called [cf-script](https://github.com/Thomascogez/cf-script) . I would like to add example scripts that will allow to make the `generate` and `migrate` command from `better-auth` work with cloudflare workers. While `better-auth/db` expose methods such as `getAuthTables`, we don't have access to generator functions included inside `better-auth/cli` package that are necessary in order to reproduce the `generate` command ### Describe the solution you'd like Export `generators` functions from `better-auth/cli` package ### Describe alternatives you've considered N/A ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 03:49:26 -05:00
Author
Owner

@Fawwaz-2009 commented on GitHub (Feb 16, 2025):

I'm also stuck on this, for context I'm trying to setup my nextjs project to be hosted on vercel and my server running on cloudflare workers

<!-- gh-comment-id:2661442490 --> @Fawwaz-2009 commented on GitHub (Feb 16, 2025): I'm also stuck on this, for context I'm trying to setup my nextjs project to be hosted on vercel and my server running on cloudflare workers
Author
Owner

@Thomascogez commented on GitHub (Feb 16, 2025):

@Fawwaz-2009 Here an example of how I handle this https://github.com/Thomascogez/better-auth-cf-demo

<!-- gh-comment-id:2661604167 --> @Thomascogez commented on GitHub (Feb 16, 2025): @Fawwaz-2009 Here an example of how I handle this https://github.com/Thomascogez/better-auth-cf-demo
Author
Owner

@Fawwaz-2009 commented on GitHub (Feb 16, 2025):

hey @Thomascogez I appreciate the response, so I end-up for now with a different solution check below. But I'm fascinated by your package cf-script.

would it be possible to have it just set the binding envs for the duration of the process eg
Inside package.json

"auth:generate": "cf-scripts @better-auth/cli generate"

This is how my current solution looks like

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { createDb } from "../db";
import path from "path";
import fs from "fs";

import { createSQLiteDB } from "@miniflare/shared";
import { D1Database, D1DatabaseAPI } from "@miniflare/d1";
import type { D1Database as D1DatabaseType } from "@cloudflare/workers-types";
const local_db = await createSQLiteDB(getLocalD1DB()!);
const db = new D1Database(new D1DatabaseAPI(local_db)) as unknown as D1DatabaseType;

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
  },
  database: drizzleAdapter(createDb(db), {
    provider: "sqlite", // or "mysql", "sqlite"
  }),
});

function getLocalD1DB() {
  try {
    const basePath = path.resolve(".wrangler");
    const dbFile = fs.readdirSync(basePath, { encoding: "utf-8", recursive: true }).find((f) => f.endsWith(".sqlite"));

    if (!dbFile) {
      throw new Error(`.sqlite file not found in ${basePath}`);
    }

    const url = path.resolve(basePath, dbFile);
    return url;
  } catch (err: any) {
    console.log(`Error  ${err.message}`);
  }
}
<!-- gh-comment-id:2661677422 --> @Fawwaz-2009 commented on GitHub (Feb 16, 2025): hey @Thomascogez I appreciate the response, so I end-up for now with a different solution check below. But I'm fascinated by your package [cf-script](https://github.com/thomascogez/cf-script). would it be possible to have it just set the binding envs for the duration of the process eg Inside package.json ```json "auth:generate": "cf-scripts @better-auth/cli generate" ``` This is how my current solution looks like ```ts import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { createDb } from "../db"; import path from "path"; import fs from "fs"; import { createSQLiteDB } from "@miniflare/shared"; import { D1Database, D1DatabaseAPI } from "@miniflare/d1"; import type { D1Database as D1DatabaseType } from "@cloudflare/workers-types"; const local_db = await createSQLiteDB(getLocalD1DB()!); const db = new D1Database(new D1DatabaseAPI(local_db)) as unknown as D1DatabaseType; export const auth = betterAuth({ emailAndPassword: { enabled: true, }, database: drizzleAdapter(createDb(db), { provider: "sqlite", // or "mysql", "sqlite" }), }); function getLocalD1DB() { try { const basePath = path.resolve(".wrangler"); const dbFile = fs.readdirSync(basePath, { encoding: "utf-8", recursive: true }).find((f) => f.endsWith(".sqlite")); if (!dbFile) { throw new Error(`.sqlite file not found in ${basePath}`); } const url = path.resolve(basePath, dbFile); return url; } catch (err: any) { console.log(`Error ${err.message}`); } } ```
Author
Owner

@tobylewis commented on GitHub (Mar 6, 2025):

Hi @Thomascogez Thanks for your efforts on this, I am trying to make an api with D1+Drizzle+Hono+better-auth. I tried using your https://github.com/Thomascogez/better-auth-cf-demo and it errored out saying the DB was undefined. Running the script given in step 2 of the cf-script readme https://github.com/Thomascogez/cf-script/blob/main/README.md the DB value was shown as
DB: ProxyStub { name: 'D1Database', poisoned: false }
I am calling this via a script in my package.json
"ba:schemas": "cf-script ./scripts/generate-better-auth-schemas.ts --env dev --wcp wrangler.jsonc"

I do have a live d1 setup in wrangler.jsonc

"env": {
"dev": {
"d1_databases": [
{
"binding": "DB",
"database_name": etc

I notice that inside the better-auth github repository there is a cloudflare example with a schema
https://github.com/better-auth/better-auth/blob/main/dev/cloudflare/src/auth-schema.ts

It seems strange that better-auth have this and yet do not seem to understand that "npx @better-auth/cli generate" will not work, not having access to the DB bindings from the CLI.

<!-- gh-comment-id:2703932021 --> @tobylewis commented on GitHub (Mar 6, 2025): Hi @Thomascogez Thanks for your efforts on this, I am trying to make an api with D1+Drizzle+Hono+better-auth. I tried using your https://github.com/Thomascogez/better-auth-cf-demo and it errored out saying the DB was undefined. Running the script given in step 2 of the cf-script readme https://github.com/Thomascogez/cf-script/blob/main/README.md the DB value was shown as DB: ProxyStub { name: 'D1Database', poisoned: false } I am calling this via a script in my package.json "ba:schemas": "cf-script ./scripts/generate-better-auth-schemas.ts --env dev --wcp wrangler.jsonc" I do have a live d1 setup in wrangler.jsonc "env": { "dev": { "d1_databases": [ { "binding": "DB", "database_name": etc I notice that inside the better-auth github repository there is a cloudflare example with a schema https://github.com/better-auth/better-auth/blob/main/dev/cloudflare/src/auth-schema.ts It seems strange that better-auth have this and yet do not seem to understand that "npx @better-auth/cli generate" will not work, not having access to the DB bindings from the CLI.
Author
Owner

@Thomascogez commented on GitHub (Mar 6, 2025):

@tobylewis Hum that seem like a bug 🤔, can you open a issue for this ? I will take a look at this

<!-- gh-comment-id:2704671336 --> @Thomascogez commented on GitHub (Mar 6, 2025): @tobylewis Hum that seem like a bug 🤔, can you open a issue for this ? I will take a look at this
Author
Owner

@jcramb commented on GitHub (Apr 11, 2025):

I'm also super keen for the generators to be exposed!

Also, if you just want to run a script with access to CF bindings I found this to be a simple straightforward solution:

  1. Create ./scripts/cf.ts'
import { getPlatformProxy } from "wrangler";

const script = async (env: Cloudflare.Env) => {
  console.log(env);
};

const platform = await getPlatformProxy({});
await script(platform.env as unknown as Cloudflare.Env);
await platform.dispose();

  1. Ensure you've run wrangler types to generate worker-configuration.d.ts which exports Cloudflare.Env.
  2. Run the script (example uses pnpm): pnpx tsx ./scripts/cf.ts
<!-- gh-comment-id:2797659172 --> @jcramb commented on GitHub (Apr 11, 2025): I'm also super keen for the generators to be exposed! Also, if you just want to run a script with access to CF bindings I found this to be a simple straightforward solution: 1. Create `./scripts/cf.ts'` ``` import { getPlatformProxy } from "wrangler"; const script = async (env: Cloudflare.Env) => { console.log(env); }; const platform = await getPlatformProxy({}); await script(platform.env as unknown as Cloudflare.Env); await platform.dispose(); ``` 2. Ensure you've run `wrangler types` to generate `worker-configuration.d.ts` which exports `Cloudflare.Env`. 3. Run the script (example uses pnpm): `pnpx tsx ./scripts/cf.ts`
Author
Owner

@serhii-chernenko commented on GitHub (May 14, 2025):

hi @jcramb
thanks for the tip. I tried your solution, but I got the error

Error: Attempted to use poisoned stub. Stubs to runtime objects must be re-created after calling `Miniflare#setOptions()` or `Miniflare#dispose()`

the actual script

import { getPlatformProxy } from 'wrangler'
import { betterAuth } from 'better-auth'
import { D1Dialect } from 'kysely-d1'

let _auth: ReturnType<typeof betterAuth>

export async function useServerAuth(env: Cloudflare.Env) {
  if (_auth) {
    return _auth
  }

  const dbName = 'DB_USERS'
  const db = env[dbName] as D1Database

  if (!db) {
    throw createError(`Database not found in ENV: ${dbName}`)
  }

  const kvStorage = 'KV_AUTH'
  const kv = env[kvStorage] as KVNamespace

  if (!kv) {
    throw createError(`KV storage not found in ENV: ${kvStorage}`)
  }

  _auth = betterAuth({
    database: {
      dialect: new D1Dialect({
        database: db,
      }),
      type: 'sqlite',
    },
    secondaryStorage: {
      get: key => kv.get(`_auth:${key}`),
      set: (key, value, ttl) => {
        return kv.put(`_auth:${key}`, value, {
          expirationTtl: ttl,
        })
      },
      delete: key => kv.delete(`_auth:${key}`),
    },
  })

  return _auth
}

const platform = await getPlatformProxy({})

export const auth = await useServerAuth(
  platform.env as unknown as Cloudflare.Env,
)

await platform.dispose()

Can you assist with this, please?

wrangler.json and worker-configuration.d.ts are generated

declare namespace Cloudflare {
	interface Env {
		KV_AUTH: KVNamespace;
		DB_USERS: D1Database;
	}
}
interface Env extends Cloudflare.Env {}
<!-- gh-comment-id:2879536676 --> @serhii-chernenko commented on GitHub (May 14, 2025): hi @jcramb thanks for the tip. I tried your solution, but I got the error ```ts Error: Attempted to use poisoned stub. Stubs to runtime objects must be re-created after calling `Miniflare#setOptions()` or `Miniflare#dispose()` ``` the actual script ```ts import { getPlatformProxy } from 'wrangler' import { betterAuth } from 'better-auth' import { D1Dialect } from 'kysely-d1' let _auth: ReturnType<typeof betterAuth> export async function useServerAuth(env: Cloudflare.Env) { if (_auth) { return _auth } const dbName = 'DB_USERS' const db = env[dbName] as D1Database if (!db) { throw createError(`Database not found in ENV: ${dbName}`) } const kvStorage = 'KV_AUTH' const kv = env[kvStorage] as KVNamespace if (!kv) { throw createError(`KV storage not found in ENV: ${kvStorage}`) } _auth = betterAuth({ database: { dialect: new D1Dialect({ database: db, }), type: 'sqlite', }, secondaryStorage: { get: key => kv.get(`_auth:${key}`), set: (key, value, ttl) => { return kv.put(`_auth:${key}`, value, { expirationTtl: ttl, }) }, delete: key => kv.delete(`_auth:${key}`), }, }) return _auth } const platform = await getPlatformProxy({}) export const auth = await useServerAuth( platform.env as unknown as Cloudflare.Env, ) await platform.dispose() ``` Can you assist with this, please? `wrangler.json` and `worker-configuration.d.ts` are generated ```ts declare namespace Cloudflare { interface Env { KV_AUTH: KVNamespace; DB_USERS: D1Database; } } interface Env extends Cloudflare.Env {} ```
Author
Owner

@dosubot[bot] commented on GitHub (Aug 13, 2025):

Hi, @Thomascogez. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary

  • You requested exposing schema generator functions from better-auth/cli to enable running generate and migrate commands within Cloudflare Workers.
  • Several users discussed workarounds and challenges with accessing DB bindings in the CLI environment.
  • You acknowledged a potential bug related to this limitation.
  • A script-based approach was shared but encountered errors, highlighting integration difficulties.
  • The issue remains unresolved with no official CLI support for this use case yet.

Next Steps

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here.
  • If I don’t hear back within 7 days, I will automatically close this issue.

Thanks for your understanding and contribution!

<!-- gh-comment-id:3184515004 --> @dosubot[bot] commented on GitHub (Aug 13, 2025): Hi, @Thomascogez. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary** - You requested exposing schema generator functions from better-auth/cli to enable running generate and migrate commands within Cloudflare Workers. - Several users discussed workarounds and challenges with accessing DB bindings in the CLI environment. - You acknowledged a potential bug related to this limitation. - A script-based approach was shared but encountered errors, highlighting integration difficulties. - The issue remains unresolved with no official CLI support for this use case yet. **Next Steps** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here. - If I don’t hear back within 7 days, I will automatically close this issue. Thanks for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8667