Первый тип контента

Тип контента — это схема. Вы задаёте поля и их типы, а DynapiCMS генерирует из них GraphQL API: запросы, мутации, фильтры, сортировку. CRUD писать не нужно.

Анатомия типа

У типа есть имя, slug и список полей. Slug задаёт имена в GraphQL: blog-post порождает blogPost (одна запись), blogPosts (список), createBlogPost (мутация). Slug — кебаб-кейс, латиница.

Каждое поле описывается так:

Свойство в UI Что значит
Название Имя поля. Станет именем в GraphQL (title, published).
Тип Тип значения (см. таблицу ниже).
Обязательно Поле обязательно при создании записи.
Сделать массивом Массив значений (не для всех типов).
Локализованное поле Разные значения для разных языков ({ru, en}).
Тип контента (для полей-ссылок) На какой тип ссылается поле.

Типы полей

В селекторе «Тип» доступны девять вариантов. В таблице — название в русском интерфейсе и английское имя (оно же type_slug в схеме):

В UI type_slug GraphQL Что это Массив Локаль
Строка string String Текст в одну строку да да
Текст text String Markdown с панелью инструментов и предпросмотром да да
Число number Float Число (с дробной частью) да да
Логический boolean Boolean Переключатель да/нет нет да
Список select String Выбор из вариантов нет да
Дата date String Дата без времени да да
Дата и время datetime DateTime Дата со временем да да
JSON json String Произвольный JSON нет да
Тип контента entity вложенный объект Ссылка на другой тип контента да да*

*Кроме полиморфных блоков (Тип контента + массив без указания типа) — их локализовать нельзя.

Тип Список (select) — это enum: значение выбирается из предопределённых вариантов. Когда выбран тип Список, под полем появляется редактор Вариантов. Каждая строка задаёт Значение (сохраняется) — что хранится в БД (например draft) — и Подпись (отображается) — что видит редактор (например Черновик). Также выбирается Значение по умолчанию. Сервер не позволяет записать значение, которого нет в списке вариантов.

Тип Текст (text) — это markdown-редактор: панель инструментов, предпросмотр, поддержка изображений. Не путайте со Строкой (string) — это обычный input в одну строку.

Ссылки между типами (поле «Тип контента»)

Поле типа «Тип контента» ссылается на другой тип. Создайте тип Author с полем name (Строка). Затем в типе Blog Post добавьте поле author («Тип контента» → Author). В GraphQL это вложенный объект — можно запросить имя автора внутри поста:

query {
  blogPosts(limit: 10) {
    title
    author {
      id
      name
    }
  }
}

Массив ссылок (Тип контента + «Сделать массивом») позволяет хранить список — например, теги или список связанных постов. Порядок элементов в массиве сохраняется.

Массивы

Флажок Сделать массивом превращает поле в список значений. Доступно для типов Строка, Текст, Число, Дата, Дата и время, Тип контента. Логический, Список и JSON массивами сделать нельзя. В GraphQL массив становится [String], [Float] и т. д.

Локализованные поля

Флажок Локализованное поле делает значение многоязычным. Запись хранится как {ru: "Привет", en: "Hello"}. При запросе через аргумент locale возвращается строка для нужного языка. Доступно для всех типов, включая ссылки на «Тип контента» (например, фоновое изображение в Hero — локализованное поле «Тип контента» → Media).

Единственное исключение: полиморфные блоки (Тип контента + «Сделать массивом» без указания типа, как blocks у Page) нельзя локализовать — сервер отклонит.

Обязательные поля

Флажок Обязательно проверяет, что поле заполнено при создании. Пустое значение (null, отсутствие ключа, пустой массив) не пройдёт проверку. Это проверка наличия — она не проверяет тип или формат.

Slug как уникальное поле

Slug типа — не то же самое, что поле slug внутри типа. Поле slug можно добавить вручную, пометить Required и использовать для красивых URL. Чтобы искать запись по слагу в GraphQL, поле должно быть помечено Unique — это добавляет аргумент slug в singular-запрос (blogPost(slug: "hello")).

Флаг Unique на данный момент нельзя поставить через интерфейс — только через схему, заданную программно. Встроенные типы (например, Page) уже имеют slug с Unique.

Как меняется схема

Сохранение типа запускает пересборку GraphQL-схемы в рантайме. Это происходит асинхронно: запрос, сохраняющий тип, возвращается сразу, а новая схема вступает в силу через доли секунды. Идущие в этот момент запросы продолжают работать со старой схемой — смена атомарна, без простоя.

Добавить поле — и оно в API. Удалить — и его нет. Мигрировать данные не нужно: записи хранятся как JSON, а схема описывает только их форму.

Что дальше