AstroDB y Turso
Instalación
- Es necesario tener alguna integración para SSR, como Node o Cloudflare
#bunx astro add db cloudflare
bunx astro add db
Tablas
- Se definen en el archivo de
config.ts
db\config.ts
import { column, defineDb, defineTable, NOW } from "astro:db";
const User = defineTable({
columns: {
id: column.text({ primaryKey: true }),
name: column.text(),
email: column.text({ unique: true }),
password: column.text(),
role: column.text({ references: () => Role.columns.id, default: "user" }),
},
});
const Role = defineTable({
columns: {
id: column.text({ primaryKey: true }),
name: column.text(),
},
});
const Product = defineTable({
columns: {
id: column.number({ primaryKey: true }),
name: column.text(),
price: column.number(),
visible: column.boolean({ default: true }),
updatedAt: column.date({ default: NOW }),
},
});
// https://astro.build/db/config
export default defineDb({
tables: {
User,
Role,
Product,
},
});
Seed
- Solo funciona en local o pruebas de desarrollo
db\seed.ts
import { db, Role, User } from "astro:db";
import bcrypt from "bcryptjs";
import { v4 as UUID } from "uuid";
// https://astro.build/db/seed
export default async function seed() {
const roles = [
{ id: "admin", name: "Admin" },
{ id: "user", name: "User" },
];
const users = [
{
id: UUID(),
name: "First Admin",
email: "[email protected]",
password: bcrypt.hashSync("123456"),
role: "admin",
},
];
await db.insert(Role).values(roles);
await db.insert(User).values(users);
}
Ejemplo uso
src\actions\index.ts
import { defineAction } from "astro:actions";
import { db, eq, User } from "astro:db";
import { z } from "astro:schema";
import bcrypt from "bcryptjs";
import { v4 as UUID } from "uuid";
export const register = defineAction({
accept: "form",
input: z.object({
name: z.string().min(2).max(50),
email: z.string().email(),
password: z.string().min(6).max(50),
}),
handler: async ({ name, email, password }) => {
// Check if email is already registered
const [user] = await db.select().from(User).where(eq(User.email, email));
if (user) throw new Error("Email already registered");
// Create user
await db.insert(User).values({
id: UUID(),
name,
email,
password: bcrypt.hashSync(password),
role: "user",
});
return true;
},
});
export const server = {
register,
};
src\pages\api\posts\likes[id].ts
export const PUT: APIRoute = async ({ request, params }) => {
const postId = params.id ?? "";
const { likes = 0 } = await request.json();
const posts = await db.select().from(Posts).where(eq(Posts.id, postId));
if (posts.length === 0) {
const newPost = {
id: postId,
likes: 0,
};
await db.insert(Posts).values(newPost);
posts.push(newPost);
}
const post = posts.at(0)!;
post.likes += Number(likes);
await db.update(Posts).set(post).where(eq(Posts.id, postId));
return new Response("Ok", { status: 200 });
};
Turso
- Crear base de datos en el dashboard de Turso
- Obtener URL y token de la nueva base de datos
- Pegar las variables en el archivo .env
.env
ASTRO_DB_REMOTE_URL=libsql://abc.turso.io
ASTRO_DB_APP_TOKEN=abc123
- Enviar cambios (nueva tabla, actualizaciones, etc.) a la base de datos
bun astro db push --remote
bun astro db push --remote --force-reset
- Usar la base de datos de la nube durante el desarrollo
bun dev --remote
Despliegue
- El comando de despliegue a producción debe tener la bandera
--remote
package.json
{
"name": "astro-app",
"scripts": {
//"dev": "astro dev --remote",
"build": "astro build --remote", // <=====
},
"dependencies": {
}
}