Drizzle + PG + Hyperdrive + Cloudflare Workers doesn't work

I've spent all the day to solve issues. At the end I left! I built a custom plugin and I ended up that cf close my db connection and the plugin doesn't work 😦 Switching back to vercel
16 Replies
bekacru
bekacru•4d ago
what is the issue?
bitangel84
bitangel84OP•4d ago
The db close the connection I used pg and hyperdrive then I tried neon serverless... same issue
bekacru
bekacru•4d ago
are using the kysley adapter?
bitangel84
bitangel84OP•4d ago
Drizzle
bekacru
bekacru•4d ago
could you try connecting using the built (kysley) adapter instead?
bitangel84
bitangel84OP•4d ago
this is a migration from vercel to cf. The app use drizzle as adapter Custom Plugin
// /signin/web3

async (ctx) => {
const data = await validateLogin(ctx.body)
if (data.error) {
return ctx.json(null, {
status: 400,
body: {
message: data.error,
status: '400',
},
})
}

const address = data.data!.addresses['chainx']

let wallet = await ctx.context.adapter.findOne<{
userId: string
chainType: string
chainName: string
coinType: number
address: string
pubkey: string
walletType: string
createdAt: Date
}>({
model: 'wallets',
where: [{
field: 'address',
value: address,
}, {
field: 'chainName',
value: 'chainx',
}]
})
...

---> here the db close the connection <---
// /signin/web3

async (ctx) => {
const data = await validateLogin(ctx.body)
if (data.error) {
return ctx.json(null, {
status: 400,
body: {
message: data.error,
status: '400',
},
})
}

const address = data.data!.addresses['chainx']

let wallet = await ctx.context.adapter.findOne<{
userId: string
chainType: string
chainName: string
coinType: number
address: string
pubkey: string
walletType: string
createdAt: Date
}>({
model: 'wallets',
where: [{
field: 'address',
value: address,
}, {
field: 'chainName',
value: 'chainx',
}]
})
...

---> here the db close the connection <---
Db
import type { Hyperdrive } from '@cloudflare/workers-types'
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres'

export function usePostgres() {
// @ts-expect-error globalThis.__env__ is not defined
const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES as Hyperdrive | undefined
const dbUrl = hyperdrive?.connectionString || process.env.NUXT_POSTGRES_URL
if (!dbUrl) {
throw createError('Missing `POSTGRES` hyperdrive binding or `NUXT_POSTGRES_URL` env variable')
}

const queryClient = postgres(dbUrl, {
ssl: !hyperdrive ? 'require' : undefined
})

return drizzle({ client: queryClient });
}
import type { Hyperdrive } from '@cloudflare/workers-types'
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres'

export function usePostgres() {
// @ts-expect-error globalThis.__env__ is not defined
const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES as Hyperdrive | undefined
const dbUrl = hyperdrive?.connectionString || process.env.NUXT_POSTGRES_URL
if (!dbUrl) {
throw createError('Missing `POSTGRES` hyperdrive binding or `NUXT_POSTGRES_URL` env variable')
}

const queryClient = postgres(dbUrl, {
ssl: !hyperdrive ? 'require' : undefined
})

return drizzle({ client: queryClient });
}
Config
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";

export const auth = betterAuth({
database: drizzleAdapter(usePostgres(), {
provider: "pg",
}),
//... the rest of your config
});
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";

export const auth = betterAuth({
database: drizzleAdapter(usePostgres(), {
provider: "pg",
}),
//... the rest of your config
});
bekacru
bekacru•4d ago
the app can use drizzle. this is jsut to allow better auth to connect it to the db
bitangel84
bitangel84OP•4d ago
I can try... at the end I don't need to modify neither
bekacru
bekacru•4d ago
yeah you just need to change the adapter and everything should be the same
bitangel84
bitangel84OP•4d ago
Failed to initialize database adapter
export function usePostgres() {
// @ts-expect-error globalThis.__env__ is not defined
const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES as Hyperdrive | undefined
const dbUrl = hyperdrive?.connectionString || process.env.NUXT_POSTGRES_URL
if (!dbUrl) {
throw createError('Missing `POSTGRES` hyperdrive binding or `NUXT_POSTGRES_URL` env variable')
}

return postgres(dbUrl, {
ssl: !hyperdrive ? 'require' : undefined
})
}

export function useKyselyDb() {
return new Kysely<KyselyDatabase>({
dialect: new PostgresJSDialect({
postgres: usePostgres(),
}),
})
}

export const auth = betterAuth({
database: useKyselyDb(),
//... the rest of your config
});
export function usePostgres() {
// @ts-expect-error globalThis.__env__ is not defined
const hyperdrive = process.env.POSTGRES || globalThis.__env__?.POSTGRES || globalThis.POSTGRES as Hyperdrive | undefined
const dbUrl = hyperdrive?.connectionString || process.env.NUXT_POSTGRES_URL
if (!dbUrl) {
throw createError('Missing `POSTGRES` hyperdrive binding or `NUXT_POSTGRES_URL` env variable')
}

return postgres(dbUrl, {
ssl: !hyperdrive ? 'require' : undefined
})
}

export function useKyselyDb() {
return new Kysely<KyselyDatabase>({
dialect: new PostgresJSDialect({
postgres: usePostgres(),
}),
})
}

export const auth = betterAuth({
database: useKyselyDb(),
//... the rest of your config
});
bekacru
bekacru•4d ago
wait so you need to wrap auth with something like getAuth higher function. Because cf requires request context for db connection
bitangel84
bitangel84OP•4d ago
is there any example?
let _auth: ReturnType<typeof betterAuth>
export function serverAuth() {
if (!_auth) {
_auth = betterAuth({
// database: drizzleAdapter(useDb(), {
// provider: 'pg',
// schema
// }),
database: {
db: useKyselyDb(),
type: 'postgres',
},
.........
} satisfies BetterAuthOptions)
}
return _auth
}
let _auth: ReturnType<typeof betterAuth>
export function serverAuth() {
if (!_auth) {
_auth = betterAuth({
// database: drizzleAdapter(useDb(), {
// provider: 'pg',
// schema
// }),
database: {
db: useKyselyDb(),
type: 'postgres',
},
.........
} satisfies BetterAuthOptions)
}
return _auth
}
stu
stu•4d ago
Could you get Better Auth working with a Hyperdrive connection? Been struggling with it for a while, and gave up. I'm using Postgres, and using the postgres connection string rather than the hyperdrive connection string ended up working for me, but it's not ideal.
bitangel84
bitangel84OP•3d ago
I still get issues
# SERVER_ERROR: Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance. (I/O type: Writable)
# SERVER_ERROR: Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. This is a limitation of Cloudflare Workers which allows us to improve overall performance. (I/O type: Writable)
bitangel84
bitangel84OP•3d ago
@bekacru I published a minimum reproducible https://nuxt-better-auth-cf.bitsong.workers.dev/ REPO: https://github.com/angelorc/nuxt-better-auth-cf 1. If you try to login with Github, you will get an error The error is The script will never generate a response. 2. If you try to refresh, then you can see your session
GitHub
GitHub - angelorc/nuxt-better-auth-cf
Contribute to angelorc/nuxt-better-auth-cf development by creating an account on GitHub.
bitangel84
bitangel84OP•2d ago

Did you find this page helpful?