23. Astro DB
Astro DB — это полноценная SQL-база данных, интегрированная непосредственно в экосистему Astro. Под капотом работает libSQL (форк SQLite от Turso), что обеспечивает высокую производительность как локально, так и в продакшне через Astro Studio.
Что такое Astro DB?
Заголовок раздела «Что такое Astro DB?»Astro DB решает типичную проблему небольших проектов: нужна база данных, но настраивать отдельный сервис PostgreSQL или MySQL слишком накладно. Astro DB даёт вам:
- Локальную SQLite-базу для разработки
- Облачную libSQL-базу через Astro Studio для продакшна
- Типобезопасный Drizzle ORM для запросов
- Встроенные миграции и сидинг
Установка: npx astro add db
Определение схемы в db/config.ts
Заголовок раздела «Определение схемы в db/config.ts»Схема базы данных описывается в специальном файле с помощью хелперов Astro DB:
import { defineDb, defineTable, column } from 'astro:db';
const User = defineTable({ columns: { id: column.number({ primaryKey: true }), name: column.text(), email: column.text({ unique: true }), role: column.text({ default: 'user' }), createdAt: column.date({ default: new Date() }), },});
const Post = defineTable({ columns: { id: column.number({ primaryKey: true }), title: column.text(), slug: column.text({ unique: true }), body: column.text(), authorId: column.number({ references: () => User.columns.id }), published: column.boolean({ default: false }), publishedAt: column.date({ optional: true }), },});
const Comment = defineTable({ columns: { id: column.number({ primaryKey: true }), body: column.text(), postId: column.number({ references: () => Post.columns.id }), authorId: column.number({ references: () => User.columns.id }), },});
export default defineDb({ tables: { User, Post, Comment },});Заполнение данными в db/seed.ts
Заголовок раздела «Заполнение данными в db/seed.ts»Файл сидинга запускается при astro dev для заполнения локальной базы тестовыми данными:
import { db, User, Post, Comment } from 'astro:db';
export default async function seed() { await db.insert(User).values([ ]);
await db.insert(Post).values([ { id: 1, title: 'Знакомство с Astro DB', slug: 'astro-db-intro', body: 'Astro DB — это...', authorId: 1, published: true, publishedAt: new Date('2024-01-15'), }, ]);}CRUD-операции с Drizzle ORM
Заголовок раздела «CRUD-операции с Drizzle ORM»Astro DB использует Drizzle ORM — типобезопасный SQL-конструктор запросов:
import { db, User, Post, Comment, eq, and, desc, count } from 'astro:db';
// SELECT — получение всех опубликованных постовconst posts = await db .select() .from(Post) .where(eq(Post.published, true)) .orderBy(desc(Post.publishedAt));
// JOIN — посты с информацией об автореconst postsWithAuthors = await db .select({ post: Post, author: User }) .from(Post) .innerJoin(User, eq(Post.authorId, User.id));
// INSERT — создание нового пользователяconst newUser = await db.insert(User).values({ name: 'Иван',}).returning();
// UPDATE — обновление ролиawait db.update(User) .set({ role: 'moderator' })
// DELETE — удаление комментарияawait db.delete(Comment).where(eq(Comment.id, 42));
// Агрегация — подсчёт комментариев к постуconst [{ total }] = await db .select({ total: count() }) .from(Comment) .where(eq(Comment.postId, 1));Использование в API-роутах
Заголовок раздела «Использование в API-роутах»import type { APIRoute } from 'astro';import { db, Post } from 'astro:db';
export const GET: APIRoute = async () => { const posts = await db.select().from(Post) .where(eq(Post.published, true)); return new Response(JSON.stringify(posts), { headers: { 'Content-Type': 'application/json' }, });};Astro Studio
Заголовок раздела «Astro Studio»Для продакшна используется Astro Studio — облачный хостинг для libSQL баз. Подключение:
npx astro db link # Связать проект с Astro Studionpx astro db push # Применить изменения схемыnpx astro db execute src/db/migration.sql # Выполнить произвольный SQL