Building and Publishing a Cosmic JS Extension Using Bitbucket Pipelines

Written by tonyspiro | Published 2020/03/12
Tech Story Tags: javascript | react | cms | api | amazon | cosmicjs | web-development | programming

TLDR Cosmic JS just released their new Extension functionally, which enables anyone to embed their own custom app inside the Cosmic CMS. In this tutorial we’ll be going through some of the steps required to make our Amazon Product Search Extension. We’re building a simple extension that allows you to search the Amazon Product Catalogue and add Objects to your bucket with products’ name, description, image, and an affiliate link. We use these keys to add new object for Amazon Products that we find.via the TL;DR App

Cosmic JS just released their new Extension functionally, which enables anyone to embed their own custom app inside the Cosmic CMS!
In this tutorial we’ll be going through some of the steps required to make our Amazon Product Search Extension.

TL;DR

The extension we’re building

We’re building a simple Extension that allows you to search the Amazon Product Catalogue and add Objects to your bucket with products’ name, description, image, and an affiliate link.
This is quite a simple app, built using react, and we won’t be going into too many details on the parts that don’t directly relate to the new Cosmic JS Extensions API.

Getting access to the Cosmic API in your Extension

Cosmic JS embeds extensions as an
<iframe>
inside its CMS interface, the extension is given a url with a querystring providing all the information needed for your app to access the relevant bucket like so:
Extracting these variables, is very easy, and even easier using a library like qs:
import qs from "qs";
const { bucket_slug, read_key, write_key, } = qs.parse(window.location.search.slice(1, Infinity));
console.log({
   bucket_slug,
   read_key,
   write_key,
});
These keys can then be used to make API calls on the bucket your currently using the extension in:
fetch(
   `https://api.cosmicjs.com/v1/${bucket_slug}/object/amazon-credentials${
      read_key
         ? "?read_key=" + read_key
         : ""
   }`,
   opts,
);
In our app we use these keys to add new object for Amazon Products that we find.

extension.json

One file that must be included in your extension is the
extension.json
file. This tells Cosmic important metadata about your app, like it's name, icon, display image, and the default Objects and Object Types that should be created when the Extension is first installed. The
extension.json
for our app is as follows:
{
  "title": "Amazon Product Search",
  "font_awesome_class": "fa-shopping-basket",
  "image_url": "http://fla.fg-a.com/shopping-cart/shopping-cart-black-3.png",
  "objects": [
    {
      "title": "Amazon Credentials",
      "slug": "amazon-credentials",
      "type": "amazon-credentials",
      "metafields": [
        {
        "key": "amz-key",
        "title": "Key",
        "type": "text",
        "value": ""
        },
        {
        "key": "amz-secret",
        "title": "Secret",
        "type": "text",
        "value": ""
        },
        {
        "key": "amz-tag",
        "title": "Tag",
        "type": "text",
        "value": ""
        }
      ]
    }
  ],
  "object_types": [
    {
      "title": "Amazon Products",
      "slug": "amazon-items",
      "singular": "Amazon Product",
      "metafields":[
        {"key":"image_url","type":"text","value":"","title":"image_url","parent":false,"children":null},
        {"key":"affiliate_link","type":"text","value":"","title":"affiliate_link","parent":false,"children":null}
      ]
    }
  ]
}
The
title
field is the name that your extension will display inside Cosmic The
font_awesome_class
field must be a valid Font Awesome icon name the
image_url
field is a display image that will show with your extension.
You also have space to specify a list of objects that will be created when your extension is installed, here we’ve detailed an object that will store our Amazon Product Search credentials. This means that Cosmic will handle saving this information for us!

Deployment and Continuous Integration

Uploading your extension to Cosmic is very easy, you just need to take a folder that contains you
extension.json
file, and an
index.html
file (and any other assets you need), zip it up, and upload it.
Our build folder looks like this:
build
├── extension.json
├── index.html
└── static
 └── js
 └── main.a651cd8a.js
You can either upload your zip file through the Cosmic JS CMS, or by using the rest API.
We use Bitbucket to host our code, which has a built in CI service called Pipelines. You can configure pipelines to run on every commit to the
master
branch of your git repo, and to upload the newest version of your app to Cosmic's servers.
We’ll configure our Bitbucket Pipeline like so:
image: codogo/pipelines-universal:latest
pipelines:
  branches:
    master:
      - step:
          script:
          - yarn install 
          - yarn run lint
          - yarn run build
          - ./uploadNewExtension.sh
Where uploadNewExtension.sh contains:
#!/bin/bash
# $BUCKET_SLUG, $READ_KEY, and $WRITE_KEY are environment variables
EXTENSION_NAME="${EXTENSION_NAME:-Amazon Product Search}"
echo "geting previous version extension id..."
PREVIOUS_EXTENSION_ID="$( curl --progress-bar "https://api.cosmicjs.com/v1/extensions-2?hide_metafields=true&read_key=foo" | jq -r ".bucket.extensions | map(select(.title == \"$EXTENSION_NAME\" )) | .[0].id"  )"
# jq is a neat little program for extracting data from json, it is available here: https://jqplay.org/
if [ "$PREVIOUS_EXTENSION_ID" == "null" ] ; then
echo "There is no '$EXTENSION_NAME' extension on cosmic to delete"
else
echo "Found id for '$EXTENSION_NAME': $PREVIOUS_EXTENSION_ID"
echo "deleting old extension..."
curl --progress-bar -X DELETE "https://api.cosmicjs.com/v1/$BUCKET_SLUG/extensions/$PREVIOUS_EXTENSION_ID" -d "{\"write_key\":\"$WRITE_KEY\"}" -H "Content-type: application/json" > /dev/null
fi
echo "upload new version of extension..."
curl --progress-bar --url "https://api.cosmicjs.com/v1/$BUCKET_SLUG/extensions" --header "content-type: multipart/form-data" --form "write_key=$WRITE_KEY" --form "zip=@./build.zip" > /dev/null
This script will remove any previously uploaded versions of our extension, then take our zipped Extension and upload it to our bucket.

Summary

In this tutorial we’ve had an introduction to the way Cosmic JS hosts and integrates with your Extension, and an explanation of how to upload your Extension using Bitbucket’s Continuous integration. If you’ve learnt something, please share this article!
If you’re making an extension, or anything else, with Cosmic JS get in touch on our Slack or Twitter, we’d love to see what you’re making.
This post was written by Codogo, an award-winning digital agency with a passion for creating amazing digital experiences.
This article was originally published on the Cosmic JS Blog.

Written by tonyspiro | CEO & Co-Founder of Cosmic JS
Published by HackerNoon on 2020/03/12