Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Подключение базы данных

До сих пор статьи жили в массиве и пропадали после перезапуска сервера. Сохраним их в базе данных SQLite — это один файл на диске, отдельный сервер не нужен. Работать с базой будем через Drizzle ORM: библиотеку, в которой таблицы описывают на TypeScript, а запросы пишут методами вместо строк SQL.

Установка

npm install drizzle-orm better-sqlite3
npm install -D drizzle-kit @types/better-sqlite3

better-sqlite3 — драйвер SQLite для Node.js, drizzle-kit — консольная утилита, которая создаёт таблицы по схеме.

Схема

Создайте файл db/schema.ts в корне проекта:

// db/schema.ts
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';
 
export const posts = sqliteTable('posts', {
  slug: text('slug').primaryKey(),
  title: text('title').notNull(),
  body: text('body').notNull(),
});
 
export const comments = sqliteTable('comments', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  postSlug: text('post_slug').notNull().references(() => posts.slug),
  author: text('author').notNull(),
  text: text('text').notNull(),
});

Каждый вызов sqliteTable описывает таблицу: её имя в базе и колонки с типами.

Создание таблиц

Утилите нужен файл настроек drizzle.config.ts в корне:

// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
 
export default defineConfig({
  dialect: 'sqlite',
  schema: './db/schema.ts',
  dbCredentials: { url: 'blog.db' },
});
npx drizzle-kit push

Команда создаст файл blog.db с таблицами posts и comments. Посмотреть и заполнить таблицы можно в браузере командой npx drizzle-kit studio.

Подключение

// db/index.ts
import Database from 'better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
 
export const db = drizzle({ client: new Database('blog.db') });

Объект db импортируют везде, где нужны запросы.

Запросы вместо массива

Перепишите lib/posts.ts. Страницы и действия вызывают те же функции, поэтому их менять не нужно:

// lib/posts.ts
import { eq } from 'drizzle-orm';
import { db } from '@/db';
import { posts } from '@/db/schema';
 
export type Post = typeof posts.$inferSelect;
 
export async function getPosts(): Promise<Post[]> {
  return db.select().from(posts);
}
 
export async function getPost(slug: string): Promise<Post | undefined> {
  const [post] = await db.select().from(posts).where(eq(posts.slug, slug));
  return post;
}
 
export async function addPost(post: Post): Promise<void> {
  await db.insert(posts).values(post);
}

Тип Post теперь выводится из схемы. Добавьте статью через форму /posts/new и перезапустите npm run dev — статья останется на месте. Так же перепишите lib/comments.ts для таблицы comments.

Основные запросы

ЗадачаКод
Все строкиdb.select().from(posts)
С условием.where(eq(posts.slug, slug))
Вставкаdb.insert(posts).values(post)
Изменениеdb.update(posts).set(data).where(...)
Удалениеdb.delete(posts).where(...)

Для PostgreSQL меняются только драйвер, dialect и функция pgTable вместо sqliteTable.

Частая ошибка

Изменить схему и забыть применить её к базе. Запрос к новой колонке завершится ошибкой «no such column». После каждой правки db/schema.ts запускайте npx drizzle-kit push, а файл blog.db добавьте в .gitignore.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.