Drizze y D1
- SQLite para Cloudflare Workers
1. Instalaciones
bun add drizzle-orm
bun add -D drizzle-kit
npm i drizzle-orm
npm i -D drizzle-kit
2. Esquemas
Crear esquemas y verificar que las importaciones sean del lugar correcto, dependiendo si se utiliza PostgreSQL, D1, SQLite, etc..
src\db\schema\units.ts
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const units = sqliteTable("units", {
id: integer({ mode: "number" }).primaryKey({ autoIncrement: true }),
displayOrder: integer("display_order", { mode: "number" }).notNull(),
title: text({ length: 255 }).notNull(),
imageSrc: text("image_src", { length: 255 }).notNull(),
});
- Sin ORM
src\db\schema.sql
DROP TABLE IF EXISTS inventory;
CREATE TABLE IF NOT EXISTS inventory (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
quantity INTEGER NOT NULL,
price REAL NOT NULL
);
CREATE INDEX idx_inventory_name ON inventory (name);
:::tip Nota Dependiendo si las tablas o la base de datos no existe entonces es necesario ejecutar las migraciones con Drizzle Kit, si ya existen entonces solo se realizan las consultas. :::
3. Cloudflare D1
1. Crear base de datos
- Con Wrangler o desde la web de Cloudflare
npx wrangler d1 create <dbName>
2. Agregar credenciales
wrangler.toml
name = "<app-name>"
main = "src/index.ts"
compatibility_date = "2024-10-29"
compatibility_flags = ["nodejs_compat"]
[[d1_databases]]
binding = "DB"
database_name = "dbName"
database_id = "dbId"
migrations_dir = "drizzle/migrations"
Drizzle Kit
1. Archivo de configuración
Puede ser TS, JS o JSON, para especificar donde se guardaran las migraciones, dónde están los esquemas y otras configuraciones.
drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
out: "./drizzle",
//schema: "./src/db/schema.ts", // Un archivo
schema: './src/db/schema', // Varios archivos
dialect: "sqlite",
});
{
"dialect": "sqlite", // "postgresql"
"out": "drizzle",
"schema": "src/db/schema.ts"
}
2. Generar migraciones
# Bun
bunx drizzle-kit generate --name=init
# NPM
npx drizzle-kit generate --name=init
3. Aplicar migraciones a la base de datos
D1 HTTP
- Si se establecieron las credenciales para D1 en
drizzle.config.ts
bunx drizzle-kit migrate
Manual
- Migraciones a la base de datos en la nube
bunx wrangler d1 execute <DB_NAME> --remote --file drizzle/0000_init.sql
- Migraciones a la base de datos local
bunx wrangler d1 execute <dbName> --local --file drizzle/0000_init.sql
Ejemplo sin middleware
- La principal diferencia al crear el cliente de una base de datos SQLite, PostgreSQL, etc. son las importaciones que se hacen, por ejemplo
import { drizzle } from "drizzle-orm/d1"; - Sin middleware es necesario crear el cliente en cada ruta
src\units\index.ts
import { drizzle } from "drizzle-orm/d1";
import { Hono } from "hono";
import { posts } from "./db/schema";
export type Env = {
DB: D1Database;
};
const unitsApp = new Hono<{ Bindings: Bindings }>();
unitsApp.get("/", async (c) => {
const db = drizzle(c.env.DB);
const result = await db.select().from(units);
return c.json(result);
});
unitsApp.post("/", async (c) => {
const db = drizzle(c.env.DB);
// Aun no tiene validaciones
// Error 500 si el JSON no trae los campos
const { displayOrder, title, imageSrc } = await c.req.json();
const result = await db
.insert(units)
.values({ displayOrder, title, imageSrc })
.returning();
return c.json(result);
});
export default unitsApp;
Ejemplo con middleware
- Con middleware se extrae la base de datos del contexto
Middleware*
src\db\drizzle-middleware.ts
import { drizzle } from "drizzle-orm/d1";
import { Context, MiddlewareHandler } from "hono";
export const ctxDB = "ctx-db";
export const drizzleMiddleware: MiddlewareHandler = async (c, next) => {
// Verificar si el cliente ya está en el contexto
if (getDrizzle(c)) return await next();
// Crear cliente de Drizzle y agregarlo al contexto
c.set(ctxDB, drizzle(c.env.DB));
await next();
};
// Función para obtener el cliente Drizzle del contexto
export const getDrizzle = (c: Context) => c.get(ctxDB);
Uso
- Agregar middleware, puede ser en algún módulo como
usersApp.use(), o en el principal,app.use() - Extraer DB
- Usar DB
src\units\index.ts
import { drizzleMiddleware, getDrizzle } from "../db/drizzle-middleware";
const unitsApp = new Hono<{ Bindings: Bindings }>();
unitsApp.use("*", drizzleMiddleware); // <==============================
unitsApp.get("/", async (c) => {
const db = getDrizzle(c); // <==============================
const result = await db.select().from(units);
return c.json(result);
});
export default unitsApp;