A Shiny New Vuejs v3 Web App Using & Deployed to Amplify/AppSync/Cognito

No cruft, let’s just start.

Prerequisites

These details plus yarn and a few other notes are available and derived from the Amplify Docs located here. What I’ve done is take those docs and add some specific details and information for this happy path. It includes additional references for the steps I took, and specifically what I’m running this on for this particular tutorial. As noted below, there is a section where this deviates from those steps and I get into next steps beyond the initial setup of the app, Amplify, and AppSync. I’ll note that part of this tutorial, or you can navigate directly to that part with this anchor thatPartiDeviate.

You’ll need the following for this specific tutorial. If you’re acclimate to various OSes and their respective needs around this software, you can get this sorted yourself and it’s mostly the same for each OS, but for this tutorial I’m rolling with MacOS Big Sur v11.6.2.

  • Your OS, as stated mine is Big Sur for this tutorial.
  • git. Probably any version released in the last decade will work just fine.
  • Node.js. Probably anything since v14 would work great but this tutorial is written against v16.11.1. As of this writing the LTS is 16.13.1 and current is 17.3.0.
  • Vue.js v3. For this tutorial I’m on a version of the v3 Preview. For the CLI a quick yarn global add @vue/cli does the job.
  • Amplify CLI. Version for this tutorial is 7.6.5. One can NPM install it with 🤙🏻 npm install -g @aws-amplify/cli or get it via cURL 👍🏻 curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL and of course, Windows has gotta be Windowsy with 😑 curl -sL https://aws-amplify.github.io/amplify-cli/install-win -o install.cmd && install.cmd.

A few first steps that only need done once. If you’ve already setup your amplify cli then this isn’t needed a second time.

First, get the Vue.js v3 base app skeleton running.

vue create mywhateverproject

Issuing this command will then provide prompts to select Vue.js v3 Preview (or likely just v3 when fully released, which will come along with other tooling as needed). Once this is done, following the standard steps of navigating into the directory cd myWhateverProejct , then executing the yarn command and finally yarn serve --open will open up the running web app in your default browser.

Next initialize the Vue.js App as an Amplify Project and get some defaults set and accepted. Executing amplify init and accepting the defaults will get this done. As displayed when done the Vue.js v3 App will now have multiple defaults and respective items selected.

Amplify Init

With the core Amplify folder and settings set, adding the Amplify libraries for use in user interface components is next up.

yarn add aws-amplify @aws-amplify/ui-components

Now navigate into the src/main.js file and add the Amplify and initial configure in the code, that will do the actual initialization execution when the app launches.

This is replacing this code…

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

with this code.

import { createApp } from 'vue'
import App from './App.vue'
import Amplify from 'aws-amplify';
import aws_exports from './aws-exports';
import {
	applyPolyfills,
	defineCustomElements,
} from '@aws-amplify/ui-components/loader';

Amplify.configure(aws_exports);
applyPolyfills().then(() => {
	defineCustomElements(window);
});
createApp(App).mount('#app')

This completes the steps we need for a running application. To cover full stack let’s cover the back end build out and schema construction. Then after that I’ll delve into thatPartiDeviate. Next up is getting the Amplify elements added.

npm install aws-amplify @aws-amplify/ui-components

Before even launching I went ahead and added the back end and database, GraphQL API, and related collateral.

amplify add api
amplify add api

Notice in the screenshot, once I selected to edit the schema now, it simply opened the file in the editor of my choice, which is Visual Studio Code for this tutorial. Since I’m executing this from the terminal in Visual Studio Code it simply opened the file in the active editor that I’m in, win win! The file that is opened by default for the schema includes the following GraphQL schema code.

# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules

input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Todo @model {
	id: ID!
	name: String!
	description: String
}

For now, I’ll just leave the comment, the input AMPLIFY and the Todo type just as it is. It’s important to note that this schema.graphql file is located at app/amplify/backend/schema.graphql. I’ll come back to this later in thatPartiDeviate.

Next I want to push the app, api, and backend to Amplify and AppSync.

amplify push

During this phase a lot of things happen. The GraphQL Schema is turned into an API and this is deployed along with the Database is deployed to DynamoDB.

To get the backend shipped, i.e. deployed to AppSync, issue the amplify push command. Again, following through with the default choices. If amplify console is issued just after this a review of the API can be made.

amplify push

Ok, now it’s auth time. Adding that is somewhat mind boggling minimal, just amplify add auth. For this I chose Default config, then Username for the way users sign in, and then the No, I am done option followed by issuing another amplify push, confirmed that and let it go through its process.

After this next steps included adding the following code to the App.vue file to get the initial interations, security and related things into place for the todo app. Again, I feel it important to note that I’ll be changing all of this later in the post here. But it’s a solid way to start building an application and then looping back around after it is up and running, deployed before moving on to next steps.

<template>
  <amplify-authenticator>
    <div id="app">
      <h1>Todo App</h1>
      <input type="text" v-model="name" placeholder="Todo name">
      <input type="text" v-model="description" placeholder="Todo description">
      <button v-on:click="createTodo">Create Todo</button>
      <div v-for="item in todos" :key="item.id">
        <h3>{{ item.name }}</h3>
        <p>{{ item.description }}</p>
      </div>
    </div>
    <amplify-sign-out></amplify-sign-out>
  </amplify-authenticator>
</template>

<script>
import { API } from 'aws-amplify';
import { createTodo } from './graphql/mutations';
import { listTodos } from './graphql/queries';
import { onCreateTodo } from './graphql/subscriptions';

export default {
  name: 'App',
  async created() {
    this.getTodos();
    this.subscribe();
  },
  data() {
    return {
      name: '',
      description: '',
      todos: []
    }
  },
  methods: {
    async createTodo() {
      const { name, description } = this;
      if (!name || !description) return;
      const todo = { name, description };
      this.todos = [...this.todos, todo];
      await API.graphql({
        query: createTodo,
        variables: {input: todo},
      });
      this.name = '';
      this.description = '';
    },
    async getTodos() {
      const todos = await API.graphql({
        query: listTodos
      });
      this.todos = todos.data.listTodos.items;
    },
    subscribe() {
      API.graphql({ query: onCreateTodo })
        .subscribe({
          next: (eventData) => {
            let todo = eventData.value.data.onCreateTodo;
            if (this.todos.some(item => item.name === todo.name)) return; // remove duplications
            this.todos = [...this.todos, todo];
          }
        });
    }
  }
}
</script>

With this added now I could run yarn serve and check out the site. At this point I signed up just to have an account to use and added a todo item. Everything worked swimmingly at this point!

The final step before getting into a proper deviation from this todo example involves now getting the app properly published to Amplify. This is done by executing amplify add hosting. Accept Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment) and Manual deployment when prompted. Now, finally, issue the command amplify publish.

Boom, the todo app site is live!

thatPartWhereiDeviate

Now it’s time to get into the nitty gritty of deviations from the easy path!

New GraphQL Schema!

My schema that I want to add is around building out collections for a number of data sets. The first one is a data set that I routinely talk about on a regular basis, and yes, it is indeed centered around trains! If you’re uninterested in the trains part and schema and more interested in the changes skip down to the "Deploying The Changes" section of the post.

Alright, describing the data model that I want to have and use will start with the minimal part of just having a list of railroads. This would be a list, or more specifically a table of railraods, that we can add railroads to and collect peripheral information about them. For this table I’ll add the following fields, AKA columns of data to store. I would want to collect the following for a railroad:

  1. railroad name
  2. wikipedia URI
  3. map URI
  4. peripheral details of an unstructured nature
  5. founding year, month, and day of the railroad
  6. record stamp

In addition, I want to keep a list of trains – specifically named trains – that each railroad operates. This data would include:

  1. train name
  2. active – yes / no
  3. peripheral details of an unstructured type
  4. wikipedia URI
  5. route map URI
  6. time table URI
  7. train URI – i.e. like a website or something that might be dedicated to the particular train.
  8. record stamp

Deploying The Changes

Now it is time to deploy these additional database and schema changes. One of the easiest ways to make these changes is to use Amplify Studio, which has a great section for data modeling, which in turn puts together and ensures your schema is usable. Then it will enable you to deploy that new schema with changes to the database and the active service!

Navigate to the interface from here.

Opening Amplify Studio with the Launch Studio button.

Once I navigated to the interface I built out the additional tables like this.

Building a Schema with Amplify Studio

Then just click on Save and Deploy and then Deploy on the following modal dialog and Amplify will deploy the AppSync schema changes.

Amplify Studio Save & Deploy

With that deployed, in the same Amplify Studio interface I then clicked on the GraphQL API tab section and then on the Resource name for mywahteverproject to open up the AppSync Console.

Opening an AppSync Schema.

Further down in the schema toward the bottom I can then find and confirm my types are in and ready for use. The Todo type is still there, since I didn’t need to really remove it yet and it acts as a good working reference. But more importantly you can see the other types and the correlative relationship that was added via the Amplify data modeling interface.

...more schema

type Todo @aws_iam
@aws_api_key {
	id: ID!
	name: String!
	description: String
	_version: Int!
	_deleted: Boolean
	_lastChangedAt: AWSTimestamp!
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
}

type Train @aws_iam
@aws_api_key {
	id: ID!
	train_name: String!
	active: Boolean!
	peripheral_details: AWSJSON
	wikipedia_uri: AWSURL
	route_map_uri: AWSURL
	timetable_uri: AWSURL
	train_uri: AWSJSON
	record_stamp: AWSTimestamp
	_version: Int!
	_deleted: Boolean
	_lastChangedAt: AWSTimestamp!
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
	railroads(
		railroadID: ModelIDKeyConditionInput,
		filter: ModelRailroadTrainFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelRailroadTrainConnection
		@aws_iam
@aws_api_key
}

type Railroad @aws_iam
@aws_api_key {
	id: ID!
	railroad: String!
	wikipedia_ur: AWSURL
	map_uri: AWSURL
	peripheral_details: AWSJSON
	founding_year: Int
	founding_month: Int
	founding_day: Int
	record_stamp: AWSTimestamp
	_version: Int!
	_deleted: Boolean
	_lastChangedAt: AWSTimestamp!
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
	RailroadTrains(
		trainID: ModelIDKeyConditionInput,
		filter: ModelRailroadTrainFilterInput,
		sortDirection: ModelSortDirection,
		limit: Int,
		nextToken: String
	): ModelRailroadTrainConnection
		@aws_iam
@aws_api_key
}

...more schema

The relationship can be seen via the object connections here in the ModelRailroadTrainConnection and the keys associated.

Next steps to get this updated in the local repository from these changes that were just made out of sync via the Amplify Studio interface requires two quick commands, both of which are displayed on the screen of the GraphQL interface in the studio. It’s best to get the command, as it’ll have the appId already included in a copypasta option on the screen, which looks like this.

amplify pull --appId app-id-which-is-in-studio --envName dev

Executing that will get everything updated and pull in the remote GraphQL Schema to the local schema.graphql file located in the amplify/backend/api/ location. Next run this command.

amplify update api

This will update everything to synchronize things, which will also prompt me for code generation so that I can have the client side code ready for use whenever I build out the user interface later.

Next Up

Some of the things I’ll cover in the next article, as I continue this effort, is what has been done with all these steps from a project perspective. As one can see, some things might be a little confusing at this point, for example the above schema shown in AppSync, but after the synchronization if you look at the schema.graphql file locally it shows this.

type Train @model @auth(rules: [{allow: public}]) {
  id: ID!
  train_name: String!
  active: Boolean!
  peripheral_details: AWSJSON
  wikipedia_uri: AWSURL
  route_map_uri: AWSURL
  timetable_uri: AWSURL
  train_uri: AWSJSON
  railroads: [RailroadTrain] @connection(keyName: "byTrain", fields: ["id"])
  record_stamp: AWSTimestamp
}

type Railroad @model @auth(rules: [{allow: public}]) {
  id: ID!
  railroad: String!
  wikipedia_ur: AWSURL
  map_uri: AWSURL
  peripheral_details: AWSJSON
  founding_year: Int
  founding_month: Int
  founding_day: Int
  record_stamp: AWSTimestamp
  RailroadTrains: [RailroadTrain] @connection(keyName: "byRailroad", fields: ["id"])
}

type Todo @model @auth(rules: [{allow: public}]) {
  id: ID!
  name: String!
  description: String
}

type RailroadTrain @model(queries: null) @key(name: "byRailroad", fields: ["railroadID", "trainID"]) @key(name: "byTrain", fields: ["trainID", "railroadID"]) @auth(rules: [{allow: public}]) {
  id: ID!
  railroadID: ID!
  trainID: ID!
  railroad: Railroad! @connection(fields: ["railroadID"])
  train: Train! @connection(fields: ["trainID"])
}

Obviously this is very different than what is shown from one place to another, so I’ll discuss this and other things. So subscribe (over on the right side of the blog), follow (@Adron), and you’ll be updated on the next post when it’s published.

SITREP (Situational Report)

Alright, what have I wrapped up so far? Here’s a bullet list of the things finished:

  • Vue.js App created.
  • Vue.js Form put together for todo entries.
  • Authentication added with Cognito.
  • An AppSync GraphQL created and published.
  • Additional types added to the AppSync GraphQL API.
  • Updates and code regenerated for our API.

What’s next to do? This is the short list, there will be after that, much more to do!

  • Get the Vue.js app spified up, get some nice design put together for it, add some reasonable CSS, graphics, etc to make the interface pop. But above all, it needs to feel usable and be usable.
  • Add the forms for each of the respective interfaces to manipulate the data. This could amount to lots of different things, adding navigation, routing, and other menues and the like.
  • Add screens that can provide some nice reports on the data that I’m putting together. For example, it’d be nice to get a list of the actual named trains or the railroads and have their images, maps, and other respective elements shown.

…and the list goes on. Until next session, enjoy your thrashing code! 🤘🏻

References

Dynamic Data Generation with JavaScript

This video shows the process detailed below in this blog entry, to provide the choice of video or a quick read! 👍🏻😁

I coded up some JavaScript to generate some data for a table recently and it seemed relatively useful, so here it is ready to use as you may. (The complete js file is below the description of the individual code segments below). This file simple data generation is something I put together to create a csv for some quick data imports into a database (Postgres, SQL Server, or anything you may want). With that in mind, I added the libraries and initialized the repo with the libraries I would need.

npm install faker
npm install fs
faker = require('faker');
fs = require('fs');

Next up I included the column row of data for the csv. I decided to go ahead and setup the variable at this point, as it would be needed as I would add the rest of the csv data to the variable itself. There is probably a faster way to do this, but this was the quickest path from the perspective of getting something working right now.

After the colum row, I also setup the base 8 UUIDs that would related to the project_id values to randomly use throughout data generation. The idea behind this is that the project_id values are the range of values that would be in the data that Subhendu would have, and all the ip and other recorded data would be recorded with and related to a specific project_id. I used a UUID generation site to generate these first 8 values, that site is available here.

After that I went ahead and added the for loop that would be used to step through and generate each record.

var data = "id,country,ip,created_at,updated_at,project_id\n";
let project_ids = [
    'c16f6dd8-facb-406f-90d9-45529f4c8eb7',
    'b6dcbc07-e237-402a-bf11-12bf2226c243',
    '33f45cab-0e14-4830-a51c-fd44a62d1adc',
    '5d390c9e-2cfa-471d-953d-f6727972aeba',
    'd6ef3dfd-9596-4391-b0ef-3d7a8a1a6d10',
    'e72c0ed8-d649-4c53-97c5-da793d7a8228',
    'bf020fd2-2514-4709-8108-a2810e61c503',
    'ead66a4a-968a-448c-a796-51c6a1da0c20'];

for (var i = 0; i < 500000; i++) {
    // TODO: Generation will go here.
}

The next thing that I wanted to sort out are the two dates. One would be the created_at value and the other the updated_at value. The updated_at date needed to show as occurring after the created_at date, for obvious reasons. To make sure I could get this calculated I added a function to perform the randomization! First two functions to get additions for days and hours, then getting the random value to add for each, then getting the calculated dates.

function addDays(datetime, days) {
    let date = new Date(datetime.valueOf());
    date.setDate(date.getDate() + days);
    return date;
}

function addHours(datetime, hours) {
    let time = new Date(datetime.valueOf())
    time.setTime(time.getTime() + (hours*60*60*1000));
    return time;
}

var days = faker.datatype.number({min:0, max:7})
var hours = faker.datatype.number({min:0, max:24})

var updated_at = new Date(faker.date.past())
var created_at = addHours(addDays(updated_at, -days), -hours)

With the date time stamps setup for the row data generation I moved on to selecting the specific project_id for the row.

var proj_id = project_ids[faker.datatype.number({min:0, max: 7})]

One other thing that I knew I’d need to do is filter for the ' or , values located in the countries that would be selected. The way I clean that data to ensure it doesn’t break the SQL bulk import process is kind of cheap and in production data I wouldn’t do this, but it works great for generated data like this.

var cleanCountry = faker.address.country().replace(",", " ").replace("'", " ")

If you’re curious why I’m calculating these before I do the general data generation and set the row up, I like to keep the row of actual data calls to either a set variable assignment or at most one dot level deep in my calls. As you’ll see now in the row level data being generated below.

data2 += 
    faker.datatype.uuid() + "," +
    cleanCountry + "," +
    faker.internet.ip() + "," +
    created_at.toISOString() + "," +
    updated_at.toISOString() + "," +
    proj_id + "\n"

Now the last step is to create the file for all these csv rows.

fs.writeFile('kundu_table_data.csv', data, function (err) {
  if (err) return console.log(err);
  console.log('Data file written.');
});

The results.

WE DID IT! DataStax Astra is GA

Yesterday we finally went full GA (General Availability) with DataStax Astra. For the quick TLDR think of it as Apache Cassandra that you can spin up as a service and use in about a minute. I, as I wrote about some months ago, joined the engineering team to help build out the system! I quickly got to reconnoitering the role and working toward build out of features, which now are available to you!

With Astra, if you’ve used Apache Cassandra or DataStax Enterprise you can use the same drivers or CQL you’re familiar with. But with Astra there are two additional capabilities we’ve just released to use in connecting to and working with your databases:

  • Astra REST API
  • Astra GraphQL API

With the REST API there are a number of capabilities to add a table, return a list of all the tables, return content of a table, and delete a table. In addition to tables, there is functionality to retrieve, retrieve all, add, update, and delete columns. All of the standard CRUD (Create, Read, Update, and Delete) commands can also be performed.

For the GraphQL API it gives you the ability to perform CRUD actions and query with filters using the GraphQL syntax.

Authorization Token

To use either of these services, the first thing you’ll need is to create one of Astra’s time based authorization tokens. These tokens work until 30 minutes after the last call made with the token. Once expired a new token must be created. To create a token an HTTP POST to the API can be made, passing several header values, and username and password in the body of a POST request.

For an example of retrieving an authorization token I’ve put together a cURL request below. To get the URL for your database navigate to the Astra dashboard, and on the summary screen of any database the API Access URL’s are listed.

curl --request POST \
  --url https://12c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/rest/v1/auth \
  --header 'accept: */*' \
  --header 'content-type: application/json' \
  --header 'x-cassandra-request-id: 24cc6f6f-c1d9-4d4e-a4d3-e34c7d8b148a' \
  --data '{"username":"betterbot","password":"betterbot"}'

A successful request will return a result with the auth token that looks like this.

{"authToken":"9a38437f-7e03-49a8-bc5d-b4e305d7c1e8"}

With that authorization token we can now call actions against the REST, or GraphQL APIs.

Creating a Table via the Astra REST API

To create a table, we need a few key elements: The table name, whether it should create if a table exists or not, and column definitions with at least one column as a primary key. This is done by using JSON to pass this schema to the REST API. Here’s an example of some JSON that can be used to create a table.

'{"name":"products","ifNotExists":true,"columnDefinitions":
  [ {"name":"id","typeDefinition":"uuid","static":false},
    {"name":"name","typeDefinition":"text","static":false},
    {"name":"description","typeDefinition":"text","static":false},
    {"name":"price","typeDefinition":"decimal","static":false},
    {"name":"created","typeDefinition":"timestamp","static":false}],"primaryKey":
    {"partitionKey":["id"]},"tableOptions":{"defaultTimeToLive":0}}'

To use this JSON to create a table, just add the pertinent headers, insert your keyspace into the URL, and the x-cassandra-token and POST this data to the REST API end point. A cURL request to create the table would look like this.

curl --request POST \
  --url https://12c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/rest/v1/keyspaces/betterbotz/tables \
  --header 'accept: */*' \
  --header 'content-type: application/json' \
  --header 'x-cassandra-request-id: 07e37064-b265-4618-94ce-1c4606f584f9' \
  --header 'x-cassandra-token: ' \
  --data '{"name":"products","ifNotExists":true,"columnDefinitions":
  [ {"name":"id","typeDefinition":"uuid","static":false},
    {"name":"name","typeDefinition":"text","static":false},
    {"name":"description","typeDefinition":"text","static":false},
    {"name":"price","typeDefinition":"decimal","static":false},
    {"name":"created","typeDefinition":"timestamp","static":false}],"primaryKey":
    {"partitionKey":["id"]},"tableOptions":{"defaultTimeToLive":0}}'

Adding data via a GraphQL Mutation

At this point, with a data created, we can add, update, or delete data. The sample curl statement I’ve put together here is a sample GraphQL mutation to add a record to the products table.

curl --request POST \
  --url https://ba965c97-86f1-4d38-8cne-58qa1d2209a1-us-east1.apps.astra.datastax.com/api/rest/v1/keyspaces/betterbotz/tables/orders/rows \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'x-cassandra-request-id: xyzaa27b-de8e-4afc-8431-8f06a326047d' \
  --header 'x-cassandra-token: 3ad1ca6a-62pq-4e1b-b273-4c08ea334909' \
  --data-raw '{"query":"mutation {superarms: insertProducts(value:{id:\"65cad0df-4fc8-42df-90e5-4effcd221ef7\"\n name:\"Arm Spec A1\" description:\"Powerful Robot Arm Spec A.\"price: \"9999.99\" created: \"2012-04-23T18:25:43.511Z\"}){value {name description price created}}}","variables":{}}'

For some other examples issuing a GraphQL mutation to add a record, just for good measure.

Go

package main

import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "https://32c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/graphql"
  method := "POST"

  payload := strings.NewReader("{\"query\":\"mutation {superarms: updateProducts(value: {id:\\\"65cad0df-4fc8-42df-90e5-4effcd221ef7\\\" name:\\\"Arm Spec A3 [Newly Updated]\\\" description:\\\"Powerful Robot Arm Spec A3.\\\" price: \\\"19999.99\\\" created: \\\"2012-04-23T18:25:43.511Z\\\" }){value {id name description price created}}}\",\"variables\":{}}")

  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)

  if err != nil {
    fmt.Println(err)
  }
  req.Header.Add("accept", "*/*")
  req.Header.Add("content-type", "application/json")
  req.Header.Add("X-Cassandra-Token", "e85b3021-fb89-4f43-9ba6-a64a49ba5f68")
  req.Header.Add("Content-Type", "application/json")

  res, err := client.Do(req)
  defer res.Body.Close()
  body, err := ioutil.ReadAll(res.Body)

  fmt.Println(string(body))
}

Python

import requests

url = "https://32c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/graphql"

payload = "{\"query\":\"mutation {superarms: updateProducts(value: {id:\\\"65cad0df-4fc8-42df-90e5-4effcd221ef7\\\" name:\\\"Arm Spec A3 [Newly Updated]\\\" description:\\\"Powerful Robot Arm Spec A3.\\\" price: \\\"19999.99\\\" created: \\\"2012-04-23T18:25:43.511Z\\\" }){value {id name description price created}}}\",\"variables\":{}}"
headers = {
  'accept': '*/*',
  'content-type': 'application/json',
  'X-Cassandra-Token': 'e85b3021-fb89-4f43-9ba6-a64a49ba5f68',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data = payload)

print(response.text.encode('utf8'))

Java

OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"query\":\"mutation {superarms: updateProducts(value: {id:\\\"65cad0df-4fc8-42df-90e5-4effcd221ef7\\\" name:\\\"Arm Spec A3 [Newly Updated]\\\" description:\\\"Powerful Robot Arm Spec A3.\\\" price: \\\"19999.99\\\" created: \\\"2012-04-23T18:25:43.511Z\\\" }){value {id name description price created}}}\",\"variables\":{}}");
Request request = new Request.Builder()
  .url("https://32c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/graphql")
  .method("POST", body)
  .addHeader("accept", "*/*")
  .addHeader("content-type", "application/json")
  .addHeader("X-Cassandra-Token", "e85b3021-fb89-4f43-9ba6-a64a49ba5f68")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();

and C#!

var client = new RestClient("https://32c3bb24-e2df-4db3-b993-14707303e57c-us-east1.apps.astra.datastax.com/api/graphql");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("accept", "*/*");
request.AddHeader("content-type", "application/json");
request.AddHeader("X-Cassandra-Token", "e85b3021-fb89-4f43-9ba6-a64a49ba5f68");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\"query\":\"mutation {superarms: updateProducts(value: {id:\\\"65cad0df-4fc8-42df-90e5-4effcd221ef7\\\" name:\\\"Arm Spec A3 [Newly Updated]\\\" description:\\\"Powerful Robot Arm Spec A3.\\\" price: \\\"19999.99\\\" created: \\\"2012-04-23T18:25:43.511Z\\\" }){value {id name description price created}}}\",\"variables\":{}}",
           ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

With that short tour, check out your free database today @ https://astra.datastax.com/register! Feel free to ping me on Twitter @Adron or here in comments, I’m open to and would love to discuss your experience!

The Fastest Way to Build a Quick Starter App with Express.js

Over the years I’ve used Express.js many times as a quick getting started example app. Since I often reference it I wanted to provide a short post that shows exactly what I do 99.9% of the time to start one of these quick Express.js reference apps. I’ve detailed in this post how to get started with Express.js the fastest way I know. There is one prerequisite, I’m assuming in this post you’ve already got Node.js installed. With that in mind, check out my installation suggestions for Node.js if you need to get that installed still. The other thing, is you’ll need to have git installed. On MacOS and Linux git is most likely installed already, if you’re on Windows I’ll leave that googling exercise up to you.

Create a directory and navigate into the directory.

mkdir quick-start-express
cd quick-start-express

Now in that directory execute the following command. Note, this command is available as of node.js 8.2.0.

npx express-generator
npm install

Inside that directory that you’ve navigated to, you’ll now have an Express.js skeleton app setup to run with the dependencies now downloaded with npm install. On MacOS or Linux run the following command to start the web app.

DEBUG=quick-start-express:* npm start

If you’re on Windows run the following command.

set DEBUG=quick-start-express:* & npm start

That’s it, one of the quickest ways to get a Node.js site up and running to start developing against!

If you’d like to dig in a bit deeper, here’s a great follow up post on creating APIs with Express. Give it a read, it’ll give you some great next steps to try out!

Cheers, and happy thrashing code!

The State of JavaScript Frameworks 2019 – A researched list of the top 5 appearing…

Quick SITREP

(If you just want the meat of the tech, skip to the “Framework Cookoff” or “Summary and Victor” section.)

I’m on vacation, so of course I’m writing and reviewing frameworks to write some code!

🤓

An Aside: Hey, if you’re on vacation and not writing code, more power to you. Gotta keep work and one’s personal life separated in as healthy a way as possible! My life however involves a lot of hobbies, that I could do professionally, and one of those hobbies I do indeed do professionally: write code, design, and understand domains to build and implement solutions for people and organizations of people!

coffee.jpgA few days ago I decided I’d create a few reference applications for development against distributed databases systems, using Apache Cassandra and whatever else. That left one of the first priorities to figure out what UI framework to use, or which to not use, or to use any at all. The application I intend to build out is a simple todo list, so nothing extravagant.

I sat down at Ballard Coffee Works today (that’s part of Seattle Coffee Works, they’re pretty rad) to get started on this. The first thing I needed to do however was figure out what the hell is going on with the state of the user interface realm of the JavaScript universe. What are my options? Are we all still just going on about React? Is Angular dead yet? What’s this Vue.js dealio? Does everybody use Bootstrap underneath all of this or has something else taken over?

Framework Cookoff!

Fire up the cooker, time to rip these frameworks apart and see which one is going to be the choice option for this task!

Bootstrap

URI: https://getbootstrap.com/

Project Self-Description:

Build responsive, mobile-first projects on the web with the world’s most popular front-end component library.

Bootstrap is an open source toolkit for developing with HTML, CSS, and JS. Quickly prototype your ideas or build your entire app with our Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful plugins built on jQuery.

My 2 Cents:

As I read the description on the website I immediately noticed “jQuery” and couldn’t recall how many times I’ve heard it’s dead, have had people swear one ought not to use it today, and generally infer to not use it. That leaves me curious if Bootstrap really is the most common open source toolkit for developing sites these days. Is it still, or is it not?

The description overall is accurate however. It is indeed focused around providing an interface design standard with HTML, CSS, and JS (JavaScript). Being able to prototype with it is very fast, and setup is something that can be done quickly even with manual setup. In other words, I don’t have to do a magical npm install and hope that everything just sets itself up. That’s a plus in my book, since I like to know the actual working parts of what I intend to and want to use.

There’s also a ton of themes for Bootstrap which I’m always excited about. Anyway to get something I can reskin with ease is a huge plus one in my book. I keep interfaces pretty simple, and aim to keep user experience uncluttered, so being able to reskin an application quickly is always like an ice cream treat on a hot day for me.

I years ago had gone through the Bootstrap introduction and reviewed it again for this article. It appears that it is as straight forward and barebones as it was years ago. Another plus in my book. Of course, going through the docs and getting some quality RTFM time in, I noticed of course there’s a npm install bootstrap these days. Why wouldn’t there be! The beautiful thing too however was that I ran this (cuz’ of course I have node.js and npm installed!) and it setup things in a pretty standard way which I immediately understood from past experience. That builds confidence that the framework and such has been consistent over the years. Another advantage for what I’m aiming to do.

This framework might just be the simple thing I’m looking for. Maybe combined with Backbone (keep reading, I did indeed stumble back into good ole’ Backbone). I’ll revamp and return after a review of all the frameworks I dig up, with a victor and the end of this post!

Angular

URI: https://angular.io/

Project Self-Description:

Angular is a platform and framework for building client applications in HTML and TypeScript. Angular is written in TypeScript. It implements core and optional functionality as a set of TypeScript libraries that you import into your apps.

The basic building blocks of an Angular application are NgModules, which provide a compilation context for components. NgModules collect related code into functional sets; an Angular app is defined by a set of NgModules. An app always…

…ok, enough of that. Basically the Angular website seemed to not have a concise description anywhere and instead just leapt directly into descriptions of the architecture. Maybe I missed it, maybe I didn’t. Upon review however that was enough to lead me down a path of determination.

I was going to review it more significantly, but see the greenfield use and existing application use has kind of just trailed off into something about turtles all the way down. With that, and the fact I’ve still never used it – somehow I managed to entirely skip that phase of JavaScript trends – I’ll just leave it were it rests and move on. It appears, based on trends, you may want to do the same thing.

React

URI: https://reactjs.org/

Project Self-Description:

Declarative – React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.

Declarative views make your code more predictable and easier to debug.

Component-Based – Build encapsulated components that manage their own state, then compose them to make complex UIs.

Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM.

Learn Once, Write Anywhere – We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code.

React can also render on the server using Node and power mobile apps using React Native.

My 2 Cents:

Ohhhhhh yeah, React is still ridiculously popular among polls and actual measured use on Github and other sites. But do I want to delve into this thing? Is it overkill for this project? Well, first off, since usage is one of the very important criteria since I hope it will continue to be a standard for some time, React is one of the top options. But I needed to research and confirm. After just a few minutes, reading about a half dozen articles it was easy to assume React still held a mantle among the most popular frameworks. It appeared with numerous tutorials and in almost every recent frameworks post listing out popular frameworks! So that’s a good start.

I do like various characteristics of React but getting it put into place on projects, it just seems like it starts to add a lot of unnecessary complexity for simple apps (especially like a todo app). In addition, it does require additional knowledge and routine RTFMing beyond the standard HTML, CSS, and JavaScript RTFMing. This could mean I might end up hacking through docs more than I do contributing to and putting together the actual todo application. But that user base which is familiar with this beast of a framework is wildly huge! So maybe I just buck up and put in the effort?

I do like a number of things about the framework, and even though I’m definitely all about the data, maybe this framework would be worth the investment in time to get better at? I checked out the tutorial in an effort to help make a decision.

Frist off, I gotta say I’m not a big fan of – and I know the industry is currently against me it appears – of have XML and HTML jammed inside of JavaScript that’s jammed inside of HTML pages that’s jammed in well… ugh. So it’s turtles all the way down. This basically looks like Classic ASP (Wikipedia) from Microsoft circa 1998, which is NOT hyperbole! Ok, enough of that point.

As I worked through the tutorial you’ve got things like a class, with HTML shoved into it like this.


class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}

view raw

reactStuff.js

hosted with ❤ by GitHub

Now, this might be some hellish looking merging of code and configuration but it is kind of slick too. You’ve got the object, in a way kind of instantiated in this code that is referred to as a class. Based on object oriented paradigms it’s like it’s a class that is also the actual instantiated object. It kind of simplifies creating a component. Component being the connector word describing both the class and object instantiation here, which by association is in reference to this being something that is rendered. Ok, all that sounds kind of complex, because conceptually it kind of is, but when you cram through enough examples it eventually starts to make sense.

If my description and comparison to object oriented programming paradigms is confusing, here’s the tutorial doc’s description, “Here, ShoppingList is a React component class, or React component type. A component takes in parameters, called props (short for “properties”), and returns a hierarchy of views to display via the render method.”

I’m not sure that helps more, being there are redundant descriptions of React component type and React component class being referenced as the same thing. Not sure I’d have made a naming decision like that, but one has to manage these definitions mentally when using a framework like this.

Weighing these types of things I’ll need to learn and also re-remember, and the factor of large and continued industry use, React is one of the top options. But still not the clear victor at this point. Let’s move on and knock a out some more reviews.

Backbone

URI: http://backbonejs.org/

Project Self-Description:

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

My 2 Cents:

Wow. I haven’t heard a peep out of anybody using Backbone since…

…recollecting memories… whiiir buzz bing pop pop, blurp, ping, ping pong.

…sometime around 2010! Wow, I can’t even believe it’s still in use but will add. It was solid then and it’s still rather solid now! I dig backbone. I however gotta say, among all my Google Kung-fu I found this an interesting one to come up as a result among user interface reviews and such. It’s not really user interface focused, it’s model based binding with events and such. Per the description from the site itself! I gave it a good ring in testing, but let’s move on to the last framework I gave a shot at today.

Vue

URI: https://vuejs.org/

Project Self-Description:

Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects. On the other hand, Vue is also perfectly capable of powering sophisticated Single-Page Applications when used in combination with modern tooling and supporting libraries.

This seems to be the hot, and I mean like blue flame hot, framework to build a user interface in JavaScript these days. It’s actually blown past React even! I guess my 1.5 year old JavaScript knowledge is just out of step at this point! Err ma gawd! I took a dive into it and made some rather pleasant discoveries!

First thing I ended up strolling through was the modern tooling and supporting libraries links:

First off I noticed jQuery had reared up in this framework too. Funny, it keeps popping back up even in spite of being declared dead by a lot of people. But meh. Check it out, I clicked on this one component and it immediately gave me some insight to how I might build an application with vue.js.

This data table component HTML looks like this. I got a little excited that it was just plain old HTML.


<datatable>
<datatable-column id="datatable-column-1" label="Column 1"></datatable-column>
<datatable-column id="datatable-column-2" label="Column 2"></datatable-column>
<datatable-column id="datatable-column-3" label="Column 3"></datatable-column>
</datatable>

Then for this type fo datatable the docs show I could create a viewmodel being wired up to bind the data into a datatable.


new Vue({
el: "#app",
data: function() {
return {
columns: [
{ id: "datatable-column-1", label: "Column 1" },
{ id: "datatable-column-2", label: "Column 2" },
{ id: "datatable-column-3", label: "Column 3" }
]
};
}
});

view raw

vuehello.js

hosted with ❤ by GitHub

Then the datatable itself.


<datatable>
<datatable-column v-for="column in columns" :id="column.id" :label="column.label"></datatable-column>
</datatable>

Ok, now that’s what I’m talking about! A viewmodel, prospectively a model somewhere binds it or populates it via a push. I didn’t know where it might be, but just looking at this it looked clean with a clearer separation of concerns than some of the other libraries, and no injected HTML or other magic black box type stuff like React has.

Nice, very nice. I liked this so much, I can see where the popularity is coming from, so research continued. Next I stepped into the introduction on the vue.js site. The first bit of code shown was this Hello.vue.


<script src="https://unpkg.com/vue"></script>
<div id="app">
<p id="hello">{{ message }} hi!</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
<style>
#hello {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

view raw

DatHello.vue

hosted with ❤ by GitHub

There was the start, with template. It seemed self-explanatory with an HTML tag “p” being the singular element, with {{ and {} signifying what I assumed is a bindable value or variable. Then below the script was clearly some JavaScript code embedded in this “DatHello.vue” file thing. Clearly readable as module providing export of JavaScript that has data, returning via function the string “Hello”. Alright, this seems pretty absurdly simple. Is it really a full framework? Finally wrapping up this file is some CSS. It doesn’t even particularly seem relevant, except that I’m guessing the CSS encapsulates the characteristics that detail how this thing should appear once it is rendered, however that happens!

Alright, that does it. It’s time to decide.

Summary and Victor

I looked at a number of articles on usage (all referenced articles are below). One can see from data collected  React climbing and climbing. Never blowing up as popular as Backbone, but upon closer inspection that doesn’t really measure exactly how many uses or users, just that it gained popularity along these curves. Vue.js on the other hand is crawling along, but based on other data, has blown up this last year or so.

Knowing this the usage and prospective usage of these frameworks put Vue.js and React in the lead. After my re-review of the tutorials and where these frameworks are today, both were still really close to victory, even though I had a happier time dealing with Vue.js and it’s respective components. One other underlying thought sitting in my mind was the fact React was just kind of a bulkier beast in concepts, and burdened with it’s history with its origins in Facebook. Not that I really cared, nor was concerned all that much. But just seeing Facebook involved as the origin and knowing it’s seedy method of extracting profits just seems like a nasty mess of spilled sour, nasty smelling, bad food sitting amid the floor while your lovely dog licks away at it. Ok, that was graphic, my apologies, but just leaving that idea with you for serious consideration.

There was one more combination that might bring things together, and that’s the ease of pulling bootstrap into things and then apply Vue.js or React together with bootstrap or something similar. What exactly was the underlying method in which these user interface frameworks could be reskinned? I did a quick follow up ~20 minutes exploration of skinning React components, what existing skins are out there, looked at some purchasable themes, looked at the same for Vue.js. One site of note that I kind of dug was vuetifyjs. It looked nice. But here I was stuck in deciding between these two.

The tie breaker was simple however. I did a search for todo apps with each respective framework, “vue.js todo apps” and “react todo apps” respectively. I reviewed them and both seemed to have plusses and minuses but then one app on Codepen, as simple as it is, sold me on a choice.

The victor is Vue.js. Just look at that Codepen sample, and look at the docs sample! It’s clean, simple, and minimalistic but the interaction is just smooth. Sure, React samples were decent, but it just seemed like more work, especially as a project grows. I’m sure some of my past history in industry has biased me somewhat, but Vue.js will work out just fine for me from the looks of things. Unless someone in this last minute can convince me otherwise! If you think I’ve made a horrible mistake, please tweet a twit at me on the twitters @Adron or message me via the ole’ contact form!

Resources – Past Articles I’ve Written:

Resources – Framework Articles: