drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
23.56k stars 579 forks source link

[FEATURE]: Cloudflare D1 HTTP driver #2086

Open Kysan opened 6 months ago

Kysan commented 6 months ago

Describe what you want

Currently we can only use D1 from a Cloudflare Worker because the drizzle() function take a D1Database instance as a parameter that can only come from a env binding of a cloudflare worker

if would be great to be able to use the DB over http to be able to use D1 outside of a cloudflare worker

here is the api that could enable this: https://developers.cloudflare.com/api/operations/cloudflare-d1-query-database

jahilliard commented 5 months ago

You can. Use this like you'd use any other client.

export async function createDbConnection() {
  if (process.env.ENVIRONMENT === 'production') console.warn('Using production database')
  return drizzle(async (sql, params, method) => {
    const url = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID!}/d1/database/${
      process.env.ENVIRONMENT === 'production'
        ? process.env.PROD_CLOUDFLARE_D1_REDIRECT_ID
        : process.env.DEV_CLOUDFLARE_D1_REDIRECT_ID
    }/query`

    const res = await fetch(url, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ sql, params, method }),
    })

    const data = await res.json()

    if (res.status !== 200)
      throw new Error(`Error from sqlite proxy server: ${res.status} ${res.statusText}\n${JSON.stringify(data)}`)
    if (data.errors.length > 0 || !data.success)
      throw new Error(`Error from sqlite proxy server: \n${JSON.stringify(data)}}`)

    const qResult = data.result[0]

    if (!qResult.success) throw new Error(`Error from sqlite proxy server: \n${JSON.stringify(data)}`)

    // https://orm.drizzle.team/docs/get-started-sqlite#http-proxy
    return { rows: qResult.results.map((r: any) => Object.values(r)) }
  })
}
QVault commented 3 months ago

Is this the intended way moving forward? since using drizzle-kit for the config seems to be doing the same thing? so unless you are using d1 on cloudflare worker, you should just http-proxy instead for client?

jahilliard commented 3 months ago

@QVault, you can't use the client. it only works in the context of cloudflare. It's a cloudflare architecture thing, not a drizzle thing. I think it has something to do with the inability to open TCP connection to a D1 database, don't quote me on that tho

WuChenDi commented 1 month ago

Hello @jahilliard

How are you doing?

I remain perplexed. As this is my inaugural experience with drizzle and the D1 database, could you guide me on how to enhance its implementation?

Here is my current approach: https://github.com/cdLab996/cf-examples-nuxt/blob/main/server/middleware/db.ts