CRUD (Create Read Update Delete) AWS Amplify + GraphQL+React Native

Димка Реактнативный
react-native-init
Published in
9 min readNov 27, 2019

--

Эта часть II является логическим продолжением части I, сериала Full Stack Serverless.

В конце этой статьи, мы с вами сделаем это мобильное приложение:

Чат поддержки: Telegram

Финальный код этой части можно найти на Github.

Введение

Создание бэкенда на AWS Amplify — это работа с бессерверной (англ. serverless) технологией, поэтому перед тем, как продолжить кодить, мы с вами разберемся с тем, что такое бессерверные вычисления и в чем их преимущества над серверными.

Прогноз ученых мужей из университета Berkeley о том как будут развиваться бэкенд технологии:

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

Мы прогнозируем, что использование без серверов будет стремительно расти. Мы также прогнозируем, что локальные гибридные облачные приложения со временем будут сокращаться, хотя некоторые развертывания могут сохраняться из-за нормативных ограничений и правил управления данными.

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

Cloud Programming Simplified: A Berkeley View on Serverless Computing

Бессерверные вычисления — естественная для облака архитектура, которая позволяет передать большую часть операционной ответственности AWS и тем самым получить больше гибкости и инновационных возможностей. Бессерверные вычисления позволяют создавать и запускать приложения и сервисы, не беспокоясь о серверах. Они устраняют необходимость заниматься вопросами управления инфраструктурой — такими, например, как выделение серверов или кластеров, необходимых ресурсов, а также установка исправлений и обслуживание операционной системы. Их можно использовать практически для любого типа приложений или сервисов серверной части, при этом всё, что требуется для запуска и масштабирования приложения с высокой доступностью, выполняется без вмешательства клиента.

Подробнее о бессерверных технологиях

Backend — Создаем API

Сейчас мы будем создавать API-интерфейс GraphQL, который взаимодействует с базой данных DynamoDB NoSQL для выполнения операций CRUD (создание, чтение, обновление, удаление).

amplify add api 

После выбраных пунктов откроется схема, которая всегда доступна для редактирования по адресу ./amplify/backend/api/messaga/schema.graphql

Куда добавляем следующий код:

Это GraphQL схема. GraphQL Transform предоставляет простую в использовании абстракцию, которая помогает быстро создавать серверные части для веб-приложений и мобильных приложений в AWS. С помощью GraphQL Transform вы определяете модель данных вашего приложения, используя язык определения схемы GraphQL (SDL), а библиотека обрабатывает преобразование определения SDL в набор полностью описательных шаблонов AWS CloudFormation, которые реализуют вашу модель данных.

При использовании вместе с такими инструментами, как Amplify CLI, GraphQL Transform упрощает процесс разработки, развертывания и поддержки API-интерфейсов GraphQL. С его помощью вы определяете свой API с помощью языка определения схемы GraphQL (SDL) и затем можете использовать автоматизацию для преобразования его в полностью описательный шаблон облачной информации, который реализует спецификацию.

GraphQL — это спецификация API. Это язык запросов для API и среда выполнения для выполнения этих запросов с вашими данными. Он имеет некоторые сходства с REST и является лучшей заменой REST.

GraphQL был представлен Facebook в 2015 году, хотя он использовался внутри компании с 2012 года. GraphQL позволяет клиентам определять структуру требуемых данных, и именно эта структура возвращается с сервера. Запрос данных таким способом обеспечивает гораздо более эффективный способ взаимодействия приложений на стороне клиента с API-интерфейсами, уменьшая количество неполных выборок и предотвращая избыточные выборки данных.

Подробней о преимуществах GraphQL здесь

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

  • Job — это тип объекта GraphQL(GraphQL Object Type), то есть тип с некоторыми полями. Большинство типов в вашей схеме будут объектными типами.
  • id position rate description owner — поля в типе Job. Это означает, что это единственные поля, которые могут появляться в любой части запроса GraphQL, работающего с типом Job.
  • String — это один из встроенных скалярных типов — это типы, которые разрешаются в один скалярный объект и не могут иметь подвыборов в запросе. Мы рассмотрим скалярные типы позже.
  • String! — поле не имеет значения NULL, означает, что служба GraphQL обещает всегда давать вам значение при запросе этого поля. Вообщем это обязательное поле.

GraphQL поставляется с набором скалярных типов по умолчанию из коробки:

  • Int 32-разрядное целое число со знаком.
  • Float значение с плавающей запятой с двойной точностью.
  • String последовательность символов UTF ‐ 8.
  • Boolean true или false.
  • IDскалярный тип ID представляет собой уникальный идентификатор, часто используемый для повторного получения объекта или в качестве ключа для кэша. Тип идентификатора сериализуется так же, как и строка; однако определение его как идентификатора означает, что он не предназначен для восприятия человеком.

Директивы

  • @model— Типы объектов, помеченные @model, являются объектами верхнего уровня в сгенерированном API. Объекты, помеченные @model, хранятся в Amazon DynamoDB и могут быть защищены с помощью @auth, связаны с другими объектами через @connection
  • @auth — Для взаимодействия приложений с вашим API GraphQL требуется авторизация. Ключи API лучше всего использовать для общедоступных API.
    Типы объектов @auth, аннотированные @auth, защищены набором правил авторизации, которые предоставляют вам дополнительные элементы управления, чем авторизация верхнего уровня в API. Вы можете использовать директиву @authдля определений типов объектов и полей в схеме вашего проекта.
    При использовании директивы@auth для определений типов объектов, которые также аннотируются @model, все средства распознавания, которые возвращают объекты этого типа, будут защищены.

Другие директивы и подробности в официальной документации.

Правила директивы @auth

@auth( rules: [ {allow: owner, ownerField: "owner", operations: [create, update, delete]} ])

означают, что операции CREATE, UPDATE, DELETE разрешены исключительно владельцу, а операция read всем.

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

amplify mock api

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

Три кита на которых стоит GraphQL:

Query (READ)

Проще говоря, запросы (queries) в GraphQL — это то, как вы собираетесь запрашивать данные. Вы получите именно те данные, которые вам нужны. Не больше, не меньше.

Mutation (CREATE UPDATE DELETE)

Мутации в GraphQL — это способ изменения данных на сервере и получения обновленных данных обратно.

Subscriptions

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

Посмотреть все доступные методы можно нажав на Docs (Documentation Explorer) в правом верхнем углу. Значения нажимаемые, таким образом можно посмотреть все возможные запросы.

CREATE

Открываем наш API по адресу, что выдал(у каждого свой) результат команды amplify mock api

и выполняем запрос CREATE нажимая кнопку плей.

Для закрепления материала, создайте еще некоторое количество вакансий.

READ

Получаем список всех вакансий. Вставляем запрос:

UPDATE

Для обновления нам необходимо взять ID вакансии (обязательно введите свой, а не из примера) и передать его в этот запрос с изменеными данными. Например обновим поля position и rate

DELETE

Для удаления нам также как и в случае с обновлением нужно передать ID вакансии (обязательно введите свой, а не из примера).

Разрешения

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

 @auth( rules: [ {allow: owner, ownerField: “owner”, operations: [create, update, delete]}, ])

Чтобы сменить пользователя нажимаем на UpdateAuth в главном меню. Где произвольно обновляем Username и Email.

Если отправим запрос READ, то он работает, но если мы отправим запрос UPDATE или DELETE и получаем ошибку.
Правила работают, что и требовалось доказать!

Теперь когда мы протестировали работоспособность API публикуем его в облако командой:

amplify push

И переходим к созданию мобильного интерфейса к созданному API в приложении React Native

FRONTEND

1. Подготовка

Для реализации этого workflow, нам потребуются следующие библиотеки:

react-navigation-tabs

@aws-amplify/api

@aws-amplify/pubsub

@aws-amplify/core

aws-amplify-react-hooks

Ставим их разом:

yarn add react-navigation-tabs @aws-amplify@1.2.4 @aws-amplify/api@1.2.4 @aws-amplify/core@1.2.4 @aws-amplify/pubsub@1.2.4 aws-amplify-react-hooks

2. Создание и верстка компонентов

Создаем компонент обертку Card
src/components/Card/index.js

Создаем компонент CardJob
src/components/CardJob/index.js

Создаем компонент CardJobDetail
src/components/CardJobDetail/index.js

Создаем InputMuliline
Редактируем src/screens/Authenticator/Form/index.js

3. AmplifyProvider

По сути тоже, что ApolloProvider у Apollo и Provider у Redux.

Предоставляет возможность передать параметры аутентификаци Auth, доступ к APIи проведение graphqlOperation из любого места приложения.

  • API - Это клиент GraphQL, который мы будем использовать для взаимодействия с конечной точкой AppSync (аналог fetch илиaxios)
  • Auth - Это класс от AWS Amplify, который обрабатывает управление пользователями. Вы можете использовать этот класс для всего: от регистрации пользователя до сброса его пароля. В этом компоненте мы будем вызывать метод Auth.user.attributes.sub, который вернет ID текущего пользователя
  • graphqlOperation - Это утилита JavaScript, которая анализирует операции GraphQL

Для того чтобы подключить его. Редактируем файл src/index.js

4.Экраны

Создаем экран JobsMain
src/screens/Jobs/JobsMain.js

На этом экране мы сделаем запрос Query, с опцией пагинации, где число через хук useQuery и он нам вернет массив, который мы отправим в Flatlist.

import { FlatList } from 'react-native'
import { listJobs } from '../../graphql/queries'
import { useQuery, getNames } from 'aws-amplify-react-hooks'
import { onCreateJob, onUpdateJob, onDeleteJob } from '../../graphql/subscriptions'
  • Flatlist - Производительный интерфейс для рендеринга списков
  • listJobs - Операция запроса GraphQL для извлечения массива данных
  • limit -Количество элементов в ответе пагинации.
  • useQuery- Хук получения данных на страницу.
  • onCreateJob onUpdateJob onDeleteJob -Операции запроса GraphQL, реализующие обновление в режиме реального времени.
  • getNames- Функция получения имен из сгенерированных Amplify запросов

Далее мы получаем данные через хукuseQuery который имеет следующий API:

const { data: Array<string>, loading, error: string, fetchMore: function } = useQuery(query {}, options: { variables: {[key: string]: any }}, queryData: Array<string>)
  • query -Первым аргументом принимает операция READ запроса GraphQL, вторым операцию подписки CREATE, третьим операцию подписки UPDATE и четвертым операцию подписки DELETE.
  • option -Объект, содержащий все переменные, которые должен выполнить ваш запрос.
  • queryData -Массив имен операций GraphQL в последовательности READ, CREATE, UPDATE, DELETE.
  • data — Возвращаемый массив данных.
  • loading -Индикатор загрузки.
  • error -Ошибки.
  • fetchMore— Часто в вашем приложении будут некоторые представления, в которых вам нужно отобразить список, который содержит слишком много данных, чтобы их можно было либо извлечь, либо отобразить сразу. Разбиение на страницы является наиболее распространенным решением этой проблемы, и хук useQuery имеет встроенную функциональность, которая делает его довольно простым. Самый простой способ сделать пагинацию — это использовать функцию fetchMore, которая включена в объект результата, возвращаемый хуком useQuery. Это в основном позволяет вам сделать новый запрос GraphQL и объединить результат с исходным результатом.

Создаем экран JobsDetail
src/screens/Jobs/JobDetail.js

Создаем экран JobAdd
src/screens/Jobs/JobAdd.js

import { createJob, updateJob, deleteJob } from '../../graphql/mutations'
import { useMutation } from 'aws-amplify-react-hooks'
  • useMutation- Хук на изменения данных.
  • сreateJob updateJob deleteJob -Операции запроса GraphQL, реализующие изменения данных.

Далее мы изменяем данные через хукuseMutation , который имеет следующий API:

const [setCreate, setUpdate, setDelete, { loading: boolean, error: string }] = useMutation(input)
  • input -Объект, содержащий все переменные, которые должен выполнить ваш запрос.
  • setCreate setUpdate setDelete -Функции, выполняющие операций GraphQL в последовательности CREATE, UPDATE , DELETE.
  • loading -Индикатор загрузки.
  • error -Ошибки.

5.Навигация

Соединям экраны в stack навигатор
src/screens/Jobs/index.js

Для логичности навигации переносим компонент User из Authenticator в директорию screens, где правим импорты

и не забываем удалить экспорт из src/screens/Authenticator/index.js

Подключаем все созданые компоненты в src/screens/index.js

Создаем TabBar
src/components/TabBar/index.js

Создаем компонент ButtonTab
src/components/TabBar/ButtonTab.js

Добавляем экспорт в src/components/index.js

Редактируем файл с конфигурацией навигации для нашей кастомной аутентификации src/AppNavigator.js

Собираем приложение и тестируем

Done✅

REFERENCES:

  1. https://aws-amplify.github.io
  2. https://aws.amazon.com/ru/cognito/
  3. https://learning.oreilly.com/library/view/full-stack-serverless/9781492059882/
  4. https://www.altexsoft.com/blog/engineering/graphql-core-features-architecture-pros-and-cons/
  5. https://engineering.fb.com/core-data/graphql-a-data-query-language/
  6. https://graphql.org/learn

--

--

Димка Реактнативный
react-native-init

Он же Димка Креативный, создатель первого в рунете курса по React Native. Активно выступающий за развитие Open Source коммьюнити.