⛈️
BunからDrizzleを用いてD1にクエリする
やむを得ずWorkersの外部からD1にクエリする場合について考える。ここではBunを用いる。
↑ サンプルコード
仕組み
REST APIを用いてD1にクエリできる。
const endpoint = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID}/d1/database/${process.env.CLOUDFLARE_DATABASE_ID}/query`
const resp = await fetch(endpoint, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
},
body: JSON.stringify({ params, sql }),
})
そしてDrizzleを用いてHTTP経由でも結果を取得できればクエリを送信できる。
const db = drizzle(async (sql, params, method) => {
return { rows: [] }
})
組み合わせると何処からでもD1にクエリできるはず。
クエリする
簡単なスキーマを定義してデータベースを初期化しておく。
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"
export const postsTable = sqliteTable("posts", {
id: integer("id").primaryKey(),
uuid: text("uuid", { length: 256 }).notNull().unique(),
title: text("title", { length: 128 }).notNull(),
text: text("text", { length: 2048 }).notNull(),
})
このようなプログラムを書く。
import { eq } from "drizzle-orm"
import { drizzle } from "drizzle-orm/sqlite-proxy"
import { postsTable } from "~/schema"
const db = drizzle(async (sql, params, method) => {
const endpoint = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID}/d1/database/${process.env.CLOUDFLARE_DATABASE_ID}/query`
try {
const resp = await fetch(endpoint, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
},
body: JSON.stringify({
params: params,
sql: sql,
}),
})
const json = await resp.json()
const [result] = json.result
if (result.error) {
throw new Error(result.error)
}
const rows = result.results.map((result: never) => {
return Object.values(result)
})
if (method === "get") {
return { rows: rows[0] }
}
return { rows: rows }
} catch (e) {
if (e instanceof Error) {
console.error(e)
}
return { rows: [] }
}
})
後は普通に呼び出す。
await db.insert(postsTable).values({
uuid: crypto.randomUUID(),
title: "Hello, World!",
text: "This is a test post.",
})
const posts = await db.select().from(postsTable).all()
console.log(posts)
const [post] = posts
const firstPost = await db
.select()
.from(postsTable)
.where(eq(postsTable.id, post.id))
.get()
console.log(firstPost)
Bunで実行する。
bun run app/main.ts
allの場合はこのように返ってくる。
[
{
id: 1,
uuid: "a89f68dc-645d-42cd-ae1f-d351093d1b7e",
title: "Hello, World!",
text: "This is a test post.",
}, {
id: 2,
uuid: "83a547f8-65f6-433f-963a-b695ed19be66",
title: "Hello, World!",
text: "This is a test post.",
}
]
最後に
もし使うならエラーを適切に取り扱ったりあとBatchにも対応が必要です。
Discussion