Reaction Commerce V3 Plugins
Reaction V3 consists out of the API, Admin, Storefront, Identity and Hydra Auth. In this blogpost we will be mainly focusing on the API and how we can create our own plugins for the API. You see Reaction comes out of the box with a lot of features, but every client that we have had wants something that is specifically tailored to their needs. In order to avoid doing extra work for future clients we can extract our Reaction code and split it up in plugins. In this blogpost I will go over how to create a very basic plugin with Queries and Mutations using both the GraphQL Resolvers and the MongoDB running inside our Reaction platform.
If you want to learn how to set up a Reaction Commerce environment I highly suggest checking out the developer platform found here: https://github.com/reactioncommerce/reaction-development-platform
What will we learn in this blogpost?
- How to use the Reaction Plugin Example
- How to setup our development environment to test plugins
- How to setup our folder structure
- How to work with the startup.js file to seed our mongoldb
- How to add a simple query
- How to create resolvers
Source code for this plugin can be found here:
Reaction Plugin Example
We can start by cloning the plugin-example from here:
https://github.com/reactioncommerce/api-plugin-example
Once we have done that we will see a folder called `src`. Inside this folder we will create our plugin. The root folder acts like any other node app that you have worked with before. We can add libraries here by using either npm install or yarn add, run listing or even run complete test suites.
Though, it is always better to test your environment as close as we can to the real thing. What we will do next is set up a connection between our local api and the plugin for the api that we just clones. If you have not setup a local api yet for reaction then I suggest you stop reading here and first do that. You can find the guide here: https://github.com/reactioncommerce/reaction-development-platform
Link our plugin as a npm package
Since version 3.7.1 Aldeed added a new way to connect plugins.
https://github.com/reactioncommerce/reaction/pull/6238
First we add our plugin to the plugins.json file, in our case:
"reaction-plugin-template": "reaction-plugin-template"
Second we have to run docker-compose up -d
to start our API.Once the API has started we can link the plugin we just created by using the new bin/package-link
function.
enter bin/package-link
and your package should now be connected to your API.
You can use this command to also push changes you made to the plugin.
Once we are done we can unlink it again like so.
bin/package-unlink
Start working on our plugin
Now we can start working on our plugin. When running docker-compose up as dev inside our Reaction API we should start seeing error messages from our plugin. Every single time we want to push some changes from our plugin to the Reaction API we have to force a refresh from nodemon. We can manually trigger this by changing something minor and readding it like a semi-colon or comma. If anyone knows a better way to link nodemon to the plugin I would love to hear it. Feel free to DM me your solution on Twitter: @SpahijaHaris
Folder structure of our Plugin
Our folder structure is going to contain a seperation of graphql functions, utility functions and mock data.
In our case we are going to create a plugin that allows us to pass the slogan from HybrIT in multiple languages.
Lets start by defining our API inside the src/index.js
file.
We will call this function registrer
This function will basically tell the API what we will use in this plugin and how it should be used.
All the functionality of our API should be stored inside the src/graphql
folder.
There we will split up everything that we need to allow Reaction to use our plugin.
We will create 1 query and 2 mutations:
- We will allow users to query for a language and get the slogan based on that language
- We will allow users to update a slogan based on a language
- We will allow users to create a new slogan based on a language
First off we can setup a folder structure like so. You can leave all the files empty, we will import them later.
At first the folder structure seems very complex, but don’t worry. I will guide you trough it.
Adding dummy data and importing it
The plugin can be seperated in 3 major components.
- GraphQL resolvers folder. All of our resolvers go in here
- Util folder. All of our extra functionality such as calculators or transformers go in here
- GraphQL mutations/queries folders. All of our MongoDB actions go in here.
The i18n contains usually information for displaying our plugin on the Reaction Admin. But we will use it for holding our dummy data in this case.
When the plugin starts up we want to make sure that we can import some data to a new collection on our MongoDB. For this we need to tell our registrer.js
what collection we are going to talk with. If the collection doesn’t exist yet, Reaction API will create it when data is imported to it.
First we need to create our dummy data. I will show you one file and just copy it and change the paramaters for the languages. Make sure you use unique i18n codes, as this will be our main way of searching documents.
And import all of the languages in the i18n/index.js
file like so
Now that we have our dummy data we can insert it into a plugin.
In order to import data we need to define our collection. In this case ExampleTemplateCollection
. We will also define our startup.js
file where we will run the import
Next we will define our startup.js
. In order to keep everything nice and tidy we will extract functionality to the util
folder.
Inside this util folder we will create two functions. One function called seedExampleTemplateCollection
and one for seedExampleTemplate
. Inside seedExampleTemplateCollection
we will define how many documents we need to insert into the collection and with what data. SeedExampleTemplate
inserts this data in individual docs.
When we save everything and refresh the Reaction API we should see a new collection being made in mongoDB.
Lets start with our queries!
Queries
In order for us fetch data we have to three things:
- Create a Schema file
- Create a query resolver
- Create the actual query to the MongoDB
I will not go over the indepth of our schema but I will just share it and explain parts of it as we go.
We can extend the existing Queries and Mutations from the Reaction API by using the extend
keyword
Our schema will look like this:
Inside of our graphql/schemas/index.js
file we will pass the schema.graphql
as a string so the API can read it and turn it into an extention of the existing GraphQL Schemas.
Our query will be called getSlogan. The idea is that we pass an enum for a language and the query returns the slogan of hybrit based on the given language.
Inside our graphql/queries/getSlogan.js
we will create a simple findOne search. We expect to receive a languageCode that we will use to search trough our collection of documents on the MongoDB. It will return the entire document to our resolver. In our index.js we will export this function
Our resolver in graphql/resolvers/Query/getSlogan.js
will call this getSlogan.js
function
Dont forget to import all the functions inside the index.js
files and the index.js registrerPlugin
function.
Mutations
Mutations work the same way as the queries. You defined a part in your schema and then create a resolver for it. This resolver usually peforms a query on your mongoDB and returns a document.
If you want to know more about mutations I highly suggest checking out the existing docs at https://docs.reactioncommerce.com/docs/graphql-create-mutation
Feel free to use the reaction-plugin-template for your own plugin!
Contact
If you are stuck with something head over to:
https://gitter.im/reactioncommerce/reaction
There are a ton of community members there that will help you out with your issues/problems.
You can also post an issue either on:
https://github.com/reactioncommerce/reaction/issues
or
https://github.com/HybrIT-dev/reaction-plugin-template/issues
Happy coding!
Haris Spahija
<code>creator @HybrIT
haris.spahija@hybrit.org
See what HybrIT can do for you? Contact our sales team!