Skip to content

Latest commit

 

History

History
726 lines (531 loc) · 39.7 KB

astro-db.mdx

File metadata and controls

726 lines (531 loc) · 39.7 KB
title description githubIntegrationURL i18nReady
Astro DB
Узнайте, как использовать Astro DB, полностью управляемую базу данных SQL, специально разработанную для Astro.
true

import { FileTree } from '@astrojs/starlight/components'; import PackageManagerTabs from '/components/tabs/PackageManagerTabs.astro'; import ReadMore from '/components/ReadMore.astro'; import StudioHeading from '~/components/StudioHeading.astro'; import { Steps } from '@astrojs/starlight/components';

Astro DB — это полностью управляемая база данных SQL, специально разработанная для Astro. Разрабатывайте локально или подключайтесь к хостингу базы данных, управляемой на нашей платформе Astro Studio.

Установка

Добавьте Astro DB в новый или существующий проект Astro (требуется [email protected] или более поздняя версия) с помощью интеграции @astrojs/db (v0.8.1 или более поздняя версия). Astro включает встроенную команду astro add для автоматизации процесса установки.

```sh npx astro add db ``` ```sh pnpm astro add db ``` ```sh yarn astro add db ```

При желании вы можете установить @astrojs/db вручную.

Определение вашей базы данных

Astro DB — это комплексное решение для конфигурирования, разработки и запроса ваших данных. Локальная база данных создается каждый раз, когда вы запускаете astro dev, используя LibSQL для управления вашими данными без необходимости использования Docker или сетевого подключения.

Установка @astrojs/db с помощью команды astro add создаст в вашем проекте файл db/config.ts, в котором вы определите таблицы вашей базы данных:

import { defineDb } from 'astro:db';

export default defineDb({
  tables: { },
})

Таблицы

Данные в Astro DB хранятся с помощью таблиц SQL. Таблицы структурируют данные в строки и столбцы, где столбцы определяют тип значения каждой строки.

Когда вы определяете таблицу, Astro генерирует интерфейс TypeScript для запроса этой таблицы из вашего проекта. В результате вы получаете полную поддержку TypeScript при доступе к данным с автозаполнением свойств и проверкой типов.

Чтобы сконфигурировать таблицу базы данных, импортируйте и используйте утилиты defineTable() и column из astro:db.

В этом примере настраивается таблица Comment с необходимыми текстовыми колонками для author и body. Затем сделайте ее доступной для вашего проекта с помощью экспорта defineDb().

import { defineDb, defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    author: column.text(),
    body: column.text(),
  }
})

export default defineDb({
  tables: { Comment },
})

См. справочник по конфигурации таблиц для полного описания параметров таблиц.

Столбцы

Данные в Astro DB хранятся с использованием таблиц SQL. Таблицы структурируют ваши данные в строки и столбцы, где столбцы определяют тип значения каждой строки. Astro DB поддерживает следующие типы столбцов:

import { defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    // Строка текста.
    author: column.text(),
    // Целочисленное значение.
    likes: column.number(),
    // Значение true или false.
    flagged: column.boolean(),
    // Значения даты/времени запрашиваются как объекты JavaScript Date.
    published: column.date(),
    // Нетипизированный JSON объект.
    metadata: column.json(),
  }
});

Смотрите справочник по столбцам таблицы для получения более подробной информации.

Ссылки на таблицы

Отношения между таблицами являются распространенным шаблоном при проектировании баз данных. Например, таблица Blog может быть тесно связана с другими таблицами Comment, Author и Category.

Вы можете определить эти отношения между таблицами и сохранить их в схеме базы данных с помощью столбцов ссылок. Чтобы установить отношения, вам понадобятся:

  • Столбец идентификатора в целевой таблице. Обычно это столбец id со свойством primaryKey.
  • Столбец в базовой таблице для хранения ссылающегося id. Для этого используется свойство references, устанавливающее связь.

В этом примере столбец Comment таблицы authorId ссылается на столбец id таблицы Author.

const Author = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    name: column.text(),
  }
});

const Comment = defineTable({
  columns: {
    authorId: column.number({ references: () => Author.columns.id }),
    content: column.text(),
  }
});

Заполнение вашей базы данных

В процессе разработки Astro будет использовать конфигурацию вашей БД для создания локальных типов в соответствии с вашими схемами. Они будут генерироваться каждый раз при запуске dev-сервера и позволят вам запрашивать и работать с формой ваших данных с безопасностью типов и автозаполнением.

Чтобы поместить данные разработки для тестирования и отладки в ваш проект Astro, создайте файл db/seed.ts. Импортируйте объект db и любую сконфигурированную таблицу из astro:db. Используйте функцию db.insert() для создания массива объектов данных строк таблицы.

Следующий пример определяет две строки данных разработки для таблицы Comment:

import { db, Comment } from 'astro:db';

export default async function() {
  await db.insert(Comment).values([
    { authorId: 1, body: 'Надеюсь, вам понравится Astro DB!' },
    { authorId: 2, body: 'Наслаждайтесь!'},
  ])
}

Ваш сервер разработки будет автоматически перезапускать вашу базу данных при каждом изменении этого файла, регенерируя ваши типы и заполняя ваши данные разработки из seed.ts.

Запрос к базе данных

Вы можете запросить вашу базу данных с любой страницы Astro или конечной точки в вашем проекте, используя предоставленные db ORM и конструктор запросов.

Drizzle ORM

import { db } from 'astro:db';

Astro DB включает встроенный клиент Drizzle ORM. Для использования клиента не требуется установка или ручная настройка. Клиент Astro DB db автоматически настраивается на взаимодействие с вашей базой данных (локальной или удалённой), когда вы запускаете Astro. Он использует вашу точную конфигурацию схемы базы данных для безопасных типизированных SQL запросов с ошибками TypeScript, если вы ссылаетесь на несуществующий столбец или таблицу.

Выборка

Следующий пример выбирает все строки таблицы Comment. Это возвращает полный массив заполненных данных разработки из db/seed.ts, который затем можно использовать в шаблоне страницы:

---
import { db, Comment } from 'astro:db';

const comments = await db.select().from(Comment);
---

<h2>Комментарии</h2>

{
  comments.map(({ author, body }) => (
    <article>
      <p>Автор: {author}</p>
      <p>{body}</p>
    </article>
  ))
}

Полный обзор можно найти в справочнике по методу select() - Drizzle ORM.

Вставка

Чтобы принимать пользовательский ввод, например, обрабатывать запросы форм и вставлять данные в удалённую базу данных, настройте проект Astro на рендеринг по запросу и добавьте адаптер SSR для вашей среды развёртывания.

В этом примере вставляется строка в таблицу Comment на основе обработанного запроса формы POST:

---
// src/pages/index.astro
import { db, Comment } from 'astro:db';

if (Astro.request.method === 'POST') {
  // парсинг данных формы
  const formData = await Astro.request.formData();
  const author = formData.get('author');
  const content = formData.get('content');
  if (typeof author === 'string' && typeof content === 'string') {
    // вставляем данные формы в таблицу Comment
    await db.insert(Comment).values({ author, content });
  }
}

// выводим новый список комментариев при каждом запросе
const comments = await db.select().from(Comment);
---

<form method="POST" style="display: grid">
	<label for="author">Автор</label>
	<input id="author" name="author" />

	<label for="content">Контент</label>
	<textarea id="content" name="content"></textarea>

	<button type="submit">Отправить</button>
</form>

<!--выводим `comments`-->

Вы также можете запросить базу данных из конечной точки API. В этом примере удаляется строка из таблицы Comment по параметру id:

// src/pages/api/comments/[id].ts
import type { APIRoute } from "astro";
import { db, Comment, eq } from 'astro:db';

export const DELETE: APIRoute = async (ctx) => {
  await db.delete(Comment).where(eq(Comment.id, ctx.params.id ));
  return new Response(null, { status: 204 });
}

Полный обзор см. в справочнике по методу insert() - Drizzle ORM.

Фильтрация

Чтобы запросить результаты таблицы по определённому свойству, используйте опции Drizzle для частичных выборок. Например, добавьте вызов .where() к вашему запросу select() и передайте сравнение, которое вы хотите сделать.

Следующий пример запрашивает все строки в таблице Comment, содержащие фразу «Astro DB». Используйте оператор like(), чтобы проверить, присутствует ли фраза внутри body:

---
import { db, Comment, like } from 'astro:db';

const comments = await db.select().from(Comment).where(
    like(Comment.body, '%Astro DB%')
);
---

Утилиты Drizzle

Все утилиты Drizzle для создания запросов доступны из модуля astro:db. Среди них:

import { eq, gt, count, sql } from 'astro:db';

Отношения

Вы можете запрашивать связанные данные из нескольких таблиц с помощью SQL-запроса join. Чтобы создать запрос с объединением, расширьте оператор db.select() оператором объединения. Каждая функция принимает таблицу для объединения и условие для сопоставления строк между двумя таблицами.

В этом примере используется функция innerJoin() для объединения авторов Comment с их связанной информацией Author на основе столбца authorId. В результате возвращается массив объектов с каждой строкой Author и Comment в качестве свойств верхнего уровня:

---
import { db, eq, Comment, Author } from 'astro:db';

const comments = await db.select()
  .from(Comment)
  .innerJoin(Author, eq(Comment.authorId, Author.id));
---

<h2>Комментарии</h2>

{
  comments.map(({ Author, Comment }) => (
    <article>
      <p>Автор: {Author.name}</p>
      <p>{Comment.body}</p>
    </article>
  ))
}

См. Справочник по соединениям Drizzle для всех доступных операторов соединения и параметров конфигурации.

Пакетные транзакции

Все удалённые запросы к базе данных выполняются как сетевой запрос. При выполнении большого количества запросов может потребоваться объединить их в одну транзакцию или обеспечить автоматический откат в случае неудачи какого-либо запроса.

В этом примере несколько строк обрабатываются одним запросом с помощью метода db.batch():

// db/seed.ts
import { db, Author, Comment } from 'astro:db';

export default async function () {
  const queries = [];
  // Добавить 100 тестовых комментариев в вашу удалённую базу данных
  // одним сетевым запросом.
  for (let i = 0; i < 100; i  ) {
    queries.push(db.insert(Comment).values({ body: `Тестовый комментарий ${i}` }));
  }
  await db.batch(queries);
}

См. документацию по Drizzle db.batch() для получения дополнительной информации.

## Astro Studio

Astro DB может подключаться к платформе Astro Studio, чтобы быстро добавить хостинг базы данных в ваш проект. Вы можете просматривать, управлять и развёртывать новые хостинговые базы данных прямо из панели управления Astro Studio.

Веб-портал Astro Studio позволяет вам подключаться и управлять вашими удаленными базами данных Astro DB через веб-интерфейс или с использованием CLI-команд.

Из вашей панели управления Studio у вас есть доступ к управлению учетной записью, справочным статьям и консоли сообщений поддержки.

Посетите Astro Studio, чтобы зарегистрироваться или войти в систему.

### Создание нового проекта Studio

Существует два способа создания проекта в Astro Studio:

  1. Использовать веб-интерфейс Astro Studio для создания из нового или существующего репозитория GitHub.

    Чтобы начать, нажмите кнопку "create project" в заголовке и следуйте инструкциям. Astro Studio подключится к вашему репозиторию GitHub и создаст новую хостинговую базу данных для вашего проекта.

  2. Использовать Astro Studio CLI для создания из любого локального проекта Astro. Для начала можно выполнить следующие команды:

    ```shell # Войдите в Astro Studio с помощью вашей учетной записи GitHub npx astro login

    Свяжите новый проект, следуя инструкциям

    npx astro link

    (Необязательно) Отправьте вашу локальную конфигурацию базы данных на удаленную базу данных

    npx astro db push

    </Fragment>
    <Fragment slot="pnpm">
    ```shell
    # Войдите в Astro Studio с помощью вашей учетной записи GitHub
    pnpm astro login
    
    # Свяжите новый проект, следуя инструкциям
    pnpm astro link
    
    # (Необязательно) Отправьте вашу локальную конфигурацию базы данных на удаленную базу данных
    pnpm astro db push
    
    ```shell # Log in to Astro Studio with your GitHub account yarn astro login

    Свяжите новый проект, следуя инструкциям

    yarn astro link

    (Необязательно) Отправьте вашу локальную конфигурацию базы данных на удаленную базу данных

    yarn astro db push

    </Fragment>
    </PackageManagerTabs>
    
    После того как вы вошли в систему и успешно подключились, вы можете выполнять все команды Astro DB для управления удаленной базой данных. 
    
     <ReadMore>О всех доступных командах см. в [справочнике Astro DB CLI](/ru/guides/integrations-guide/db/#справочник-по-cli-astro-db).</ReadMore>
    
    
### Развёртывание с подключением к Studio

Вы можете развернуть свой проект Astro DB с живым подключением к вашей базе данных Studio. Это возможно на любой платформе развёртывания с использованием статических сборок или адаптера SSR.

Сначала настройте свою команду сборки для подключения к Studio с использованием флага --remote. В этом примере флаг применяется к скрипту "build" в файле package.json вашего проекта. Если ваша платформа развёртывания принимает команду сборки, убедитесь, что она установлена на npm run build.

{
  "scripts": {
    "build": "astro build --remote"
  }
}
#### Создание токена приложения Studio

Для доступа к вашей базе данных Studio из продакшн-развёртывания вам нужно создать токен приложения. Вы можете создать токен приложения на панели управления вашего проекта Studio, перейдя на вкладку Settings и выбрав Tokens.

Скопируйте сгенерированный токен и примените его в качестве переменной окружения / секрета окружения на вашей платформе развёртывания, используя имя ASTRO_STUDIO_APP_TOKEN.

### Настройте действие GitHub CI

Вы можете автоматически отправлять изменения схемы в вашу базу данных Studio с использованием действия Studio CI. Это позволит убедиться, что изменения могут быть внесены безопасно, и поддерживать конфигурацию в актуальном состоянии при каждом слиянии с main.

Следуйте документации GitHub, чтобы настроить новый секрет в вашем репозитории с именем ASTRO_STUDIO_APP_TOKEN и вашим токеном приложения Studio в качестве значения секрета.

После того как секрет настроен, создайте новый файл рабочего процесса GitHub Actions в директории проекта .github/workflows для проверки репозитория и установки Node.js в качестве шагов, а также используйте действие withastro/action-studio для синхронизации изменений схемы.

После настройки секрета создайте новый файл рабочего процесса GitHub Actions в директории проекта .github/workflows для проверки репозитория и установки Node.js в качестве шагов, а также используйте действие withastro/action-studio для синхронизации изменений схемы.

Действие запустит astro db verify на всех событиях-триггерах, чтобы убедиться, что изменения схемы могут быть применены безопасно. Если вы специально добавите триггер push, действие перенесет эти изменения в базу данных Studio.

Приведенный пример GitHub Action _studio.yml отправляет изменения при каждом обновлении ветки main:

name: Astro Studio

env:
  ASTRO_STUDIO_APP_TOKEN: ${{secrets.ASTRO_STUDIO_APP_TOKEN }}

on:
  push:
    branches:
      - main
  pull_request:
    types: [opened, reopened, synchronize]

jobs:
  DB:
    permissions:
      contents: read
      actions: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - uses: jaid/[email protected]
      - uses: withastro/action-studio@main
### Отправка схем таблиц

Схема вашей таблицы будет изменяться со временем по мере роста вашего проекта. Вы можете безопасно тестировать изменения конфигурации локально и отправлять их в вашу базу данных Studio при развёртывании.

При создании проекта Studio из панели управления вы сможете создать действие CI GitHub. Это автоматически мигрирует изменения схемы при слиянии с основной веткой вашего репозитория.

Вы также можете отправлять изменения схемы через CLI, используя команду astro db push:

```sh npm run astro db push ``` ```sh pnpm astro db push ``` ```sh yarn astro db push ```

Эта команда проверит, можно ли внести изменения без потери данных, и подскажет, какие изменения схемы рекомендуется внести для разрешения конфликтов. Если изменение схемы должно быть выполнено, добавьте флаг --force-reset, чтобы сбросить все производственные данные.

Внесение критических изменений в схему

:::caution Это уничтожит вашу базу данных. Выполняйте эту команду только в том случае, если вам не нужны производственные данные. :::

Если вам необходимо изменить схему таблиц таким образом, чтобы она была несовместима с существующими данными, размещёнными в Astro Studio, вам придется перезагрузить свою производственную базу данных.

Чтобы отправить обновление схемы таблицы, содержащее разрушающее изменение, добавьте флаг --force-reset, чтобы сбросить все производственные данные:

```sh npm run astro db push --remote --force-reset ``` ```sh pnpm astro db push --remote --force-reset ``` ```sh yarn astro db push --remote --force-reset ``` ### Переименование таблиц

Можно переименовать таблицу после загрузки схемы в Astro Studio.

Если у вас нет важных производственных данных, то вы можете сбросить базу данных, используя флаг --force-reset. Этот флаг сбросит все таблицы в базе данных и создаст новые, чтобы они точно соответствовали вашей текущей схеме.

Чтобы переименовать таблицу, сохранив при этом производственные данные, необходимо выполнить ряд необратимых изменений, чтобы безопасно перенести локальную схему в студию Astro.

В следующем примере таблица переименована из Comment в Feedback:

  1. В файле конфигурации базы данных добавьте свойство deprecated: true для таблицы, которую вы хотите переименовать:

    const Comment = defineTable({
      deprecated: true,
      columns: {
        author: column.text(),
        body: column.text(),
      }
    });
  2. Добавьте новую схему таблицы (точно соответствующую свойствам существующей таблицы) с новым именем:

    const Comment = defineTable({
        deprecated: true,
      columns: {
        author: column.text(),
        body: column.text(),
      }
    });
    
    const Feedback = defineTable({
        columns: {
          author: column.text(),
          body: column.text(),
        }
    });
  3. Отправьте изменения в Astro Studio с помощью команды astro db push --remote. Это добавит новую таблицу и пометит старую как устаревшую.

  4. Обновите любой локальный код проекта, чтобы использовать новую таблицу вместо старой. Возможно, вам также потребуется перенести данные в новую таблицу.

  5. Когда вы убедитесь, что старая таблица больше не используется в вашем проекте, вы можете удалить схему из вашего config.ts:

    const Comment = defineTable({
          deprecated: true,
        columns: {
          author: column.text(),
          body: column.text(),
        }
    });
    
    const Feedback = defineTable({
          columns: {
            author: column.text(),
            body: column.text(),
          }
    });
  6. Снова перейдите в Astro Studio с помощью astro db push --remote. Старая таблица будет удалена, останется только новая, переименованная таблица.

### Отправка данных

Вам может потребоваться отправить данные в вашу базу данных Studio для заполнения или миграции данных. Вы можете создать файл .ts с помощью модуля astro:db для написания типобезопасных запросов. Затем выполните этот файл в базе данных Studio с помощью команды astro db execute <file-path> --remote:

Следующие комментарии могут быть добавлены с использованием команды astro db execute db/seed.ts --remote:

// db/seed.ts
import { Comment } from 'astro:db';

export default async function () {
  await db.insert(Comment).values([
    { authorId: 1, body: 'Hope you like Astro DB!' },
    { authorId: 2, body: 'Enjoy!' },
  ])
}

См. Справочник по CLI для ознакомления с полным списком команд.

### Подключение к Astro Studio

По умолчанию Astro использует локальный файл базы данных при выполнении команд dev или build. Таблицы создаются с нуля при выполнении каждой команды, и в них вставляются исходные данные для разработки.

Чтобы подключиться к вашей хостинговой базе данных Studio, вы можете добавить флаг --remote. Используйте этот флаг для развёртывания на производство с возможностью чтения и записи в вашу базу данных Studio. Это позволит вам принимать и сохранять данные пользователей.

# Сборка с удалённым подключением
astro build --remote

# Разработка с удалённым подключением
astro dev --remote

:::caution

Будьте осторожны, используя --remote в разработке. Это приведет к подключению к живой продакшн-базе данных, и все вставки, обновления или удаления будут сохранены.

:::

Чтобы использовать удалённое подключение, вам понадобится токен приложения для аутентификации в Studio. Инструкции по созданию и настройке токена можно найти на приборной панели Studio.

Когда вы будете готовы к развёртыванию, ознакомьтесь с нашим Руководством по развёртыванию с подключением к Studio.

Создание интеграций Astro DB

Интеграции Astro позволяют расширить пользовательские проекты дополнительными таблицами и данными для заполнения Astro DB.

Используйте метод extendDb() в хуке astro:db:setup для регистрации дополнительных конфигурационных файлов Astro DB и файлов данных для заполнения. Вспомогательная функция defineDbIntegration() обеспечивает поддержку TypeScript и автозаполнение для хука astro:db:setup.

// my-integration/index.ts
import { defineDbIntegration } from '@astrojs/db/utils';

export default function MyIntegration() {
  return defineDbIntegration({
    name: 'my-astro-db-powered-integration',
    hooks: {
      'astro:db:setup': ({ extendDb }) => {
        extendDb({
          configEntrypoint: '@astronaut/my-package/config',
          seedEntrypoint: '@astronaut/my-package/seed',
        });
      },
      // Другие интеграционные хуки...
    },
  });
}

Файлы конфигурации config и seed для интеграции следуют тому же формату, что и их пользовательские аналоги.

Типобезопасные операции в интеграциях

При работе над интеграциями вы можете не воспользоваться сгенерированными Astro типами таблиц, экспортированными из astro:db. Для обеспечения полной безопасности типов используйте утилиту asDrizzleTable() для создания объекта-ссылки на таблицу, который можно использовать для операций с базой данных.

Например, в интеграции задана следующая таблица базы данных Pets:

// my-integration/config.ts
import { defineDb, defineTable, column } from 'astro:db';

export const Pets = defineTable({
  columns: {
    name: column.text(),
    species: column.text(),
  },
});

export default defineDb({ tables: { Pets } });

Файл данных может импортировать Pets и использовать asDrizzleTable() для вставки строк в вашу таблицу с проверкой типов:

// my-integration/seed.ts
import { asDrizzleTable } from '@astrojs/db/utils';
import { db } from 'astro:db';
import { Pets } from './config';

export default async function() {
  const typeSafePets = asDrizzleTable('Pets', Pets);

  await db.insert(typeSafePets).values([
    { name: 'Мурка', species: 'кошка' },
    { name: 'Бублик', species: 'собака' },
  ]);
}

Значение, возвращаемое asDrizzleTable('Pets', Pets), эквивалентно import { Pets } из 'astro:db', но доступно даже тогда, когда генерация типов Astro не может быть запущена. Вы можете использовать его в любом коде интеграции, который требует запросов или вставок в базу данных.