На этой неделе мы собираемся запачкать руки и начать программировать.

Введение

Статья прошлой недели была первой из серии статей о построении системы электронной коммерции с использованием Keystone.js, и в основном она была посвящена системным требованиям и ее базовой архитектуре. На этой неделе мы собираемся немного запачкать руки и начать программировать. Сначала поговорим о среде разработки и ее настройке. Затем о настройке Keystone и Next, и, наконец, о настройке базовых моделей. Также готовый код этой статьи доступен на моем GitHub.

Настройка среды разработки

Давайте запустим и создадим папку проекта для нашей системы, в моем случае keystone-e-commerce, и создадим несколько необходимых файлов. Выполните следующую команду в консоли:

mkdir keystone-e-commerce && cd keystone-e-commerce
touch README.md docker-compose.dev.yml .gitignore .env.example .env

Согласно предыдущей статье, уровень данных этой системы содержит два элемента: базу данных и поисковую систему. Самый простой способ использовать их локально в нашей среде разработки — использовать для этого Docker. Итак, пришло время обновить наш файл docker-compose.dev.yaml. Просто добавьте следующее:

Кроме того, я добавил сюда pgAdmin. Это приятный и очень полезный инструмент, особенно в среде разработки. Далее необходимо настроить переменные окружения для системы. Самый простой способ сделать это — создать один файл .env и использовать его во всех контейнерах. Хорошо, давайте добавим все необходимые переменные, как показано ниже:

Я уже добавил переменные, необходимые для интеграции Cloudinary; мы вернемся
к ним позже. Затем обновите файл .gitgnore. На данный момент этого достаточно. Следующий код поможет:

**/node_modules
.env

Теперь, с этой базовой настройкой, мы можем запустить наши контейнеры с помощью этой команды:

docker-compose -f docker-compose.dev.yml up

Настройка Kesytone.js и Next.js

Выполнив эту настройку, мы можем сосредоточиться на других частях системы. Во-первых, давайте создадим наше клиентское приложение Next.js. Честно говоря, здесь мы только создадим его и добавим в нашу настройку Docker. Дальнейшая работа с ним будет выполнена в следующих статьях этой серии. Запустим соответствующую команду:

yarn create next-app --typescript

Скрипт запросит у нас название приложения. Я назвал своего client. После установки нам нужно создать Dockerfile.dev для этого приложения, чтобы использовать его с другими контейнерами. Как видите, это довольно просто:

FROM node:16
WORKDIR /usr/app
CMD yarn dev -p 3000

Кроме того, обновите файл docker-compose.dev.yml в разделе services с помощью этого кода:

Подобное решение позволяет использовать один основной файл .env, что удобно и обеспечивает централизованный контроль над всеми системными секретами. Кроме того, он инкапсулирует всю систему в одну закрытую сеть докеров. И на данный момент это все об этой части приложения. Итак, переходим к бэкэнд части и настраиваем Kesytone.js.

Сначала запустите скрипт для создания приложения. Я выбрал backend в качестве имени папки для него.

yarn create keystone-app

После этого он в основном готов к использованию, но сначала нам нужно обновить базу данных и другие конфигурации. В keystone.ts добавьте учетные данные и обновите импорт для списков:

Затем создайте дополнительные папки, чтобы иметь красивую и простую для понимания структуру, с помощью этого кода:

mkdir consts enums schema

Кроме того, импорт в основной файл конфигурации требует, чтобы мы добавили index.ts в папку schema для правильной работы. Осталось сделать последний элемент настройки — создать файл Dockerfile.dev и обновить docker-compose.dev.yml. Он будет очень похож на предыдущий, как показано ниже:

FROM node:16
WORKDIR /usr/app
CMD yarn dev

Это также позволит нам запустить всю систему одной командой.

Настройка моделей

После завершения настройки мы можем начать и создать все необходимые списки Keystone (и модели данных в нашем случае). Начнем с модели User. По сути, он будет хранить все пользовательские данные, включая роли и привилегии внутри системы. Создайте user.schema.ts в папке схемы. На данный момент нас интересует только свойство fields списка. Мы должны добавить туда все необходимые поля, как вы можете видеть ниже:

Поля name, email и password довольно очевидны. Его целью является идентификация user, и он необходим для процесса авторизации и аутентификации. Требуются все три из них. Кроме того, email должен быть уникальным, и в пользовательском интерфейсе администратора его можно использовать для фильтрации всех пользователей. Более интересным является поле role. Его тип — select, и он содержит информацию о привилегиях пользователя в системе. Он создаст столбец enum в базе данных, чтобы он оставался красивым и чистым. Я перенес значения параметров в отдельный файл в папке consts.

Вот код:

Также я переместил все значения в файл в папке enums:

Пока этих двух ролей достаточно. Позже нам понадобится больше из них. Последнее поле содержит ссылку на список Address. Точнее, это отношение «один ко многим». Следующий список содержит все адреса, связанные с пользователями; каждый может иметь более одного. Итак, создайте address.schema.ts, как показано ниже:

Этот список содержит всю необходимую адресную информацию, которая потребуется при отправке заказов пользователей. Большинство полей являются обязательными для предоставления достаточной информации о доставке. Также этот список содержит временные метки создания записи и ее последней модификации. Последнее поле — это ссылка на user, владельца этого адреса, и в данном случае это отношение «многие к одному».

Далее, со списком user тесно связана модель Cart. Он содержит всю информацию о товарах, добавленных пользователем в корзину, их сумму и дату последнего изменения. У каждого пользователя есть один Cart, поэтому это отношение один к одному. Вот код:

В каждом Cart может быть добавлено много продуктов, и один и тот же продукт может быть добавлен в несколько корзин, поэтому создается отношение «многие ко многим».

После этого мы можем сосредоточиться на других моделях. Далее, связанный с User и слабо связанный с Cart список Order. Он содержит всю информацию о заказах, находящихся в обработке и уже обработанных. Первое поле — это ссылка на user, владельца этого заказа, отношения «один-к-маю». У каждого пользователя может быть несколько заказов, но у каждого заказа есть только один владелец.

Следующее поле содержит информацию о продуктах в этом порядке, сериализованную в JSON. Таким образом, мы можем упорядочить информацию обо всех продуктах, не только о тех, которые в настоящее время есть в наличии, но и о тех, которые были удалены из предложения.

Затем два поля содержат отношение к спискам Payment и Shipment, оба отношения один к одному. Последние три поля содержат информацию о дате создания, последней модификации и статусе заказа. Последний находится в типе выбора, я переместил все параметры и значения в отдельные файлы, как раньше с ролями пользователей.

Следующие два списка дополняют модель Order и содержат информацию о Payment и Shipment, связанных с ней. Оба они содержат основную информацию о временных метках и статусах обоих бизнес-процессов (созданных так же, как статус заказа) и их связи с Order.

Первый из них дополнительно содержит информацию о сумме заказов, его валюте и идентификаторе транзакции от стороннего поставщика. Я пока не думал о конкретной интеграции в этом вопросе, но, вероятно, это будет Полоса, потому что она мне наиболее знакома.

С другой стороны, модель Shipment содержит информацию о сотрудниках, ответственных за обработку этого груза, его упаковку и отправку. Аналогично, как и в предыдущем, также есть информация о внешнем идентификаторе от сторонней системы, отвечающей за обработку доставки.

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

Последняя группа моделей ориентирована на продукты. Основной список Product содержит основную информацию о продукте, такую ​​как name, description, SEO description, price, rating (звездочки) и timestamps. Остальные поля устанавливают различные отношения к более конкретной информации о продукте, такой как изображения продуктов, категории и акции.

Первый создает отношение «один ко многим»; второй — отношение «многие ко многим», а последний — отношение «один к одному». По сути, у товара может быть несколько изображений, но изображение принадлежит только одному товару. Каждая категория может иметь категории, а категория — много продуктов, и, наконец, каждая из них имеет только одну информацию о запасах (как я упоминал в предыдущей статье, я решил поддерживать только одну настройку склада).

Следующий список содержит изображения продуктов. Здесь есть два важных поля: alt и image. Первый содержит информацию, необходимую для заполнения HTML-атрибута alt для каждого изображения. Второй позволяет загружать изображения прямо в Cloudinary CDN. Все это дополнено полями временных меток.

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

Последняя модель, Category, содержит информацию о категориях продуктов и их отношениях друг с другом. Поля здесь включают category name, related products и parent category (если есть) и обычное timestamps. Эта внутренняя взаимосвязь позволяет легко создавать дерево категорий, которое будет полезно при создании внешнего интерфейса нашей системы.

Последнее, что нужно сделать, это импортировать все модели в index.ts, который импортируется в основной файл конфигурации keystone.ts, показанный ниже:

Небольшое примечание о метках времени. Каждая из них имеет набор значений по умолчанию и не должна редактироваться пользователями. Но об этом в следующей статье.

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

docker-compose -f docker-compose.dev.yml up database

После этого запускаем в отдельном терминале нашего бэкенда:

cd backend && yarn dev

Скрипт запросит имя новой миграции, введите initial_models и нажмите Enter. Он будет обрабатывать создание таблицы и генерировать файлы миграции. Теперь мы можем остановить оба процесса и запустить всю систему.

docker-compose -f docker-compose.dev.yml up database

Краткое содержание

Теперь у нас есть рабочая среда разработки и настройка базовых моделей, так что это дает нам прочную основу для нашей системы. В следующий раз мы начнем создавать дополнительные функции, необходимые в системе электронной коммерции. Во-первых, мы сосредоточимся на контроле доступа и привилегиях пользователей для доступа к различным частям системы.

Надеюсь, вам понравилось. Если у вас есть какие-либо вопросы или комментарии, не стесняйтесь спрашивать.

Хорошего дня!