Announcing The Aurelia 2 Book

Buy the Aurelia 2 book here.

With the Aurelia 2 alpha coming very shortly, I have had plans for a while to write another Aurelia book, this time around on Aurelia 2. I learned a lot writing my first book and admittedly, made a few mistakes. The learning experience was invaluable.

With my first book, it came at a time when the Aurelia documentation was subpar. The book served as more of a stand-in for the lack of detailed and concise documentation. With Aurelia 2, extensive documentation work has been undertaken to the point where a book telling you about every little thing makes no sense.

The Aurelia 2 documentation which is updated regularly can be found here if you are wondering where it is located.

This time around, I wanted to write a book that is different from the first, something fun. So, I set out one night to start writing the Aurelia 2 book, not really having a clear goal in mind and after a couple of days, I had one.

The book will touch upon the fundamentals without parroting the documentation too much, it will support TypeScript and you will build an application using Aurelia 2 to get acquainted. The app you will be building is an online cat pictures store, where you can buy pictures of cats.

What You’ll Learn

In the book you’ll learn not only how to develop an Aurelia application, you”ll get to learn how to work with the great new convention-based router, how to structure your app, how to break things up into components, how to leverage new Aurelia 2 features.

On-top of building an application, you will also learn the crucial skill of how to write unit tests with Jest and how to write integration tests using Cypress to test your application. The book aims to go beyond just being solely about Aurelia 2, giving you practical skills.

What You’ll Build

An online store for selling cat pictures. It’ll have a homepage, category page, a detail page, a checkout screen and logged in/logged out functionality as well. An accompanying local server running SQLlite will allow your app to feel real as things are persisted.

The application will touch upon how you can add in authentication, how you can create routes, creating secured sections and other fundamentals that will translate across to actual real world applications.

Introductory minimum price: $4.99

For early adopters who want to support the development of the book, getting updates as the book goes along, you can get it for as low as $4.99. This is the early adopter price because the book is still in its early days of authoring.

Over time as the book becomes more complete, the minimum price will be increased. If you purchase now, you will get access to all future updates for free at the reduced minimum price. Of course, if you are feeling generous, you can opt to pay more than the minimum and every dollar is appreciated, but not expected.

Please be aware that the book structure is still being finalised, chapters added and moved around. There will be typos, mistakes in the code and possibly even things that change in Aurelia 2 itself which get removed or added to the book.

As Aurelia 2 evolves in development, so too, will the book. For the entire life of Aurelia 2, the book will be updated in step to remain an up-to-date resource. You only purchase once and all future updates to the book are free.

Buy the Aurelia 2 book here.

How To Generate An SSH Key and Add The Public Key To A Remote Server

The thing with SSH authentication is I can never remember the steps to generate an SSH key, and then add that SSH public key to the remote server so SSH authentication works.

I had all of this in a text file, but honestly, I reference my own blog for knowledge on how to do things all of the time, I thought I’d write up a quick post.

You can find numerous blog posts on this, but I always seem to find a straightforward explanation to give me what I need, that I just consulted my text file on my desktop.

Generating An SSH Key

This will generate both private and public keypairs.

ssh-keygen -t rsa -b 4096 -C "johnsmith@gmail.com"
# Generates a new private and public keypair, using the email as the label

You’ll be asked to enter a keyphrase. Personally, I don’t use keyphrases for my keys (I know I probably should). So, I skip the following.

Enter passphrase (empty for no passphrase):
Enter same passphrase again:

For the key names, by default it’ll generate id_rsa and id_rsa.pub but you can name these whatever you want. Because I am dealing with CI providers like Travis CI and GitHub Actions, I generate keys every time I do something with a server.

Add Your Public Key To The Remote Server

Basically, we copy the contents of the public key and store it in the authorized_keys file in the .ssh folder on the server.

cat ~/.ssh/id_rsa.pub | ssh username@domain.com 'cat >> ~/.ssh/authorized_keys'

If you kept the default name, keep id_rsa.pub as the key name. For username@domain.com add in your server username and the server domain name or IP address. The second string part just copies the contents of the file into the authorized_keys file on the server.

How To Add Feature Flags Into Your Javascript Applications

Feature flags are a great way to prevent stale branches by regularly shipping features in your code without officially enabling them. A feature flag let’s you turn code on and off, in the case of features, a feature flag means you can regularly merge branches and release them.

While there are many different ways you can approach this, one of my favourite and most simple approaches is a features.json file in your application.

It can be something as simple as a JSON file of properties and boolean values.

{
    "feature1": true,
	"feature2": false
}

Or in the case of something more flexible and less straightforward it can be something like this where we can specify specific roles who are allowed to use a certain feature.

{
    "feature1": {
        "roles:" ["admin", "editor"]
        "enabled": true
    },
    "feature2": {
        "enabled": false
    }
}

In your code, you import the features.json file and then reference the features. Depending on your framework or environment, this will look different.

import features from './features.json';

const FeatureOne = features.feature1 ? import ('./features/feature-one') : null;

If you were to do this in a framework like Angular or Aurelia, you would create a service or middleware of some kind which compares the route against the property in your features file and reacts accordingly.

import features from './features.json';

export class FeatureService {
    getFeature(key) {
        return features?.[key] ?? null;
    }
}

There are a few feature flag services out there which provide SDK’s and ways to turn features on and off, do A/B testing, but for most use-cases, you don’t need anything else other than a JSON file and a little code to wire it all up.

How To Do Prepared Statement LIKE With SQLlite 3 and The Better SQLite 3 Package

I love SQLite and I am using it in my Aurelia 2 book for the server aspect to provide users with a real server backed by a database. I am using the equally brilliant Better SQLite 3 library which allows you to work with SQLite 3 databases in a performant and easy way.

This is how I did a prepared statement for my LIKE query which searched products by title in my database. The statement itself needs LIKE ? and then on the all method we provide the argument.

Using the template literal syntax with backticks, we handle our wildcard syntax and value in there. You can use whatever pattern you want here, but my use case needed %${query}%

const db = sqlite('mydatabase.db');

const rows = db.prepare(`SELECT * FROM products WHERE title LIKE ?`).all(`%${query}%`);

It’s simple and it works beautifully. Presumably, this would also work for other SQLite 3 libraries, but I highly recommend the Better SQLite 3 library for working with SQLite databases.

How To Get Last 4 Digits of A Credit Card Number in Javascript

Recently whilst working on my Aurelia 2 book, for the example application where you checkout I needed to add in the ability to provide a card number and when it saves, the last 4 digits of the card number get saved.

This is one of those things that as developers we won’t do too often, but it’s easy using substr to trim a text string to a certain length.

let ccNumber = '4560265043620583';
let lastFourDigits = ccNumber.substr(-4);

By providing -4 as the value to substr you’re telling it to take the last 4 characters from the string. The result from our example will be 0583. You can also provide non-negative numbers to go from the beginning as well.

I am sure there are other ways of doing the same thing, but I always look for the easiest to read and easiest to understand solutions and substr fits the bill nicely.

Level Up Aurelia Store With pluck and distinctUntilChanged

Aurelia Store is a powerful state management library for your Aurelia applications, but behind-the-scenes it merely wraps the powerful RxJS observable library. This means you can use a plethora of RxJS methods to change how Aurelia Store works.

Problem: Aurelia Store will fire all state subscribers regardless of change

Whenever your state changes, all listeners of the state object will be fired. While smaller applications won’t introduce any noticeable differences, as your application grows in size and complexity, depending on what you’re doing inside of those store subscribers you can run into some issues.

Sometimes you only want code to run inside of an Aurelia Store subscription if it needs too, akin to some kind of if statement that checks if the code needs to be run.

For example, if you have a isLoading property in your store that changes depending on whether or not something is loading, any code that watches this property should only fire when it changes, not whenever the store’s state changes. Why should isLoading checks care if you’ve loaded a bunch of users or products data?

Solution

Using the RxJS methods pluck and distinctUntilChanged, we can tell our subscriptions to only fire if a specific property in our store has changed. The pluck method allows us to tell RxJS to only watch a specific property in our state object. For the above loading example, we would want to “pluck” the isLoading property pluck('isLoading').

Lastly, we want to use the distinctUntilChanged method which accepts no arguments. All it does is takes our “plucked” value and compares it to its previous value to see if it changed or not.

import { distinctUntilChanged, pluck } from 'rxjs/operators';

this.store.state.pipe(pluck('isLoading'), distinctUntilChanged()).subscribe((isLoading) => {
    // The isLoading property changed
});

Now, this works great for most use cases. However, as documented in the distinctUntilChanged the documentation details a caveat on how the check works you need to be aware of.

distinctUntilChanged uses === comparison by default, object references must match!

If you want to do a check based on an object property, you need to use the distinctUntilKeyChanged method which is not covered in this post.

Really, that is all there is to it. You pluck a property and then you do a distinct check to react whether or not the value has changed. This is all just RxJS code and nothing overly Aurelia Store specific. There are a tonne of other RxJS operators you should read up on.

How To Fix HiveJS AssertionError “Expected version 128, instead got 149” and “Expected version 128, instead got 38”

If you are trying to use any methods in the HiveJS client which require the use of a private key, you might have encountered one or both of these errors.

In my case, I was using the memo encode method which takes a private key as the first argument, unfortunately, pass it the wrong key and you’ll get a non-helpful AssertionError about an expected version.

You’re seeing the error because you’re providing the wrong key. If you get the error, “AssertionError: Expected version 128, instead got 38” it means you are trying to use a public key when you need to use a private key.

In my instance, the error, “AssertionError: Expected version 128, instead got 149” was because I was attempting to use my account password instead of my private memo key to encode the memo string.

These errors really need to be changed to be more helpful, right now they’re as cryptic as the functionality itself.

Forget CSS-In-JS: Combine Sass With CSS Modules Using Webpack

I really dislike the CSS-In-JS trend. Nothing against anyone who is a fan, but writing CSS inside of Javascript doesn’t feel natural and honestly, it’s just an unnecessary abstraction. I understand why it became a thing, but the problems CSS-In-JS promises to solve have already been solved thanks to CSS Modules and Shadow DOM.

As usual, the front-end development community are focused on tooling and not on the end-user experience. Numerous benchmarks have proven CSS-In-JS can introduce performance issues into your application.

For cross-platform development, I will not dispute CSS-In-JS solutions can be useful, but many of us only target one platform most of the time. The thought of having to write components for even the most simple of UI tasks sounds daunting.

I am a big fan of using CSS Modules in my projects. They solve the naming issue in CSS giving you the same result as something like Styled Components, only you get to write CSS inside of CSS files. In combination with a pre-processor, even better.

Separating module and non-module SCSS

When using CSS Modules in your application, it is considered best practice to separate your module and non-module CSS styles. If you treat all CSS/SCSS as a CSS Module, when working with third-party packages with CSS/SCSS such as Bootstrap, you will run into problems.

I like to treat all CSS/SCSS as non-module by default. For CSS Modules, you want to specifically opt-in to use the modules functionality. This way you can have traditional global CSS and when you want localised component styles, you opt-in.

For module styles I like to use the .module.scss or .module.css naming convention. Inside of my components I will do something like this:

import styles from './mycomponent.module.scss';

In my case, I am using autoprefixer as well as cssnano to add browser prefixes and de-duplicate my CSS styles when imported. Your webpack.config.js configuration might look slightly different to this, alter to your taste.

Define the loaders

const cssModuleRules = [{
        loader: 'css-loader',
        options: {
            importLoaders: 2,
            sourceMap: true,
            modules: {
                localIdentName: '[name]__[local]____[hash:base64:5]',
            },
        }
    },
    {
        loader: 'postcss-loader',
        options: {
            plugins: () => [
                require('autoprefixer')(),
                require('cssnano')()
            ]
        }
    }
];

const cssRules = [{
        loader: 'css-loader'
    },
    {
        loader: 'postcss-loader',
        options: {
            plugins: () => [
                require('autoprefixer')(),
                require('cssnano')()
            ]
        }
    }
];

We have two CSS Loader configurations here, one for CSS Modules and one for standard CSS.

The following loader configurations going inside of the module rules property.

{
    test: /\.css$/i,
    use: extractCss ? [{ loader: MiniCssExtractPlugin.loader }, ...cssRules] : ['style-loader', ...cssRules]
},
{
    test: /\.scss$/,
    exclude: /\.module\.scss$/,
    use: extractCss ? [{ loader: MiniCssExtractPlugin.loader }, ...cssRules, ...sassRules] : ['style-loader', ...cssRules, ...sassRules],
},
{
    test: /\.module\.scss$/,
    use: extractCss ? [{ loader: MiniCssExtractPlugin.loader }, ...cssModuleRules, ...sassRules] : ['style-loader', ...cssModuleRules, ...sassRules]
}

We have a CSS rule for being able to deal with standard CSS, not using modules. Then we have a scss rule for non-module scss styling. And lastly, we have a rule for module styles using our CSS Modules configuration.

If you wanted to use CSS Modules with standard CSS, you could easily add another rule testing for .module.css to allow that as well.

That is all there really is to it. Now, you have CSS Modules allowing locally scoped CSS that will have randomly generated class name strings, allowing you to write specific CSS without global naming conflicts.

The Australian CovidSafe App Doesn’t Even Work On iOS Properly

And the government wonders why people were sceptical of the CovidSafe rollout (besides the very real safety concerns). It seems the CovidSafe rollout is flawed, with the discovery that the iOS version doesn’t even work properly.

Software developer Joshua Byrd recently posted his findings on Twitter and they’re pretty damning. Basically, the app will only ever work in the foreground with the screen on for iOS users.

On a technical level as explained in further Tweets, the phone will not broadcast UUID’s unless it is open. Coincidentally, the same issue was reported with Singapore’s app which CovidSafe is based upon and seemingly, nobody learned their lesson from.

Basically, unless you are aware of the power saving mode which just makes you leave the app open in your pocket upside down meaning you can’t use any other apps, the app itself is useless for a majority of iOS users.

Apple and Google have been working on their own OS level contact tracing API’s and presumably, it would be in the interest of the Australian government to migrate over to these API’s asap. Not only from a technical perspective, but also to alleviate privacy concerns users have over the app being used in the future as a surveillance tool.

Why Is Voat Still A Thing?

Remember Voat? The non-censored alternative to Reddit that saw an influx of users in 2015 after Reddit started cleaning up its house a bit and claims of censorship became a hot button issue that drove people away from Reddit.

The site has now become an anti-vaxxer, conspiracy theorist platform that resembles an uncontrollable raging dumpster fire. Although to be fair, the site was always teetering on the edge even in the beginning.

After Reddit started banning subreddits such as those dedicated to PizzaGate, many moved over to Voat. And when the whole QAnon thing came to be and Reddit subsequently banned that community, they also moved to Voat.

As you can see, Voat sure knows how to attract the right people to its platform. I haven’t been to the site in years, so it was an interesting experience to go and see what constitutes front-page material these days and well, the screenshots speak for themselves.

Given the COVID-19 pandemic is a hot button issue right now, it is not unexpected to see a tonne of paranoid conspiracy theories surrounding vaccinations and COVID-19.

My question is, how is Voat even still alive? Many of its subverses (sub communities) seem to be completely dead like /v/javascript and the only ones that seem to be thriving are the conspiracy theory sub communities.