На этой неделе мы собираемся запачкать руки и начать программировать.
Введение
Статья прошлой недели была первой из серии статей о построении системы электронной коммерции с использованием 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
Краткое содержание
Теперь у нас есть рабочая среда разработки и настройка базовых моделей, так что это дает нам прочную основу для нашей системы. В следующий раз мы начнем создавать дополнительные функции, необходимые в системе электронной коммерции. Во-первых, мы сосредоточимся на контроле доступа и привилегиях пользователей для доступа к различным частям системы.
Надеюсь, вам понравилось. Если у вас есть какие-либо вопросы или комментарии, не стесняйтесь спрашивать.
Хорошего дня!