Monthly Archives: November 2019

inversify

I wanted to use an IoC pattern/library in a project I was working on (a node server application where I would slot in the specific implementations of the data and services at runtime).

I cam across inversify, there may be other IoC’s for TypeScript, but this is the one I looked into and worked a treat for me.

yarn add inversify reflect-metadata

You will need to enable experimentalDecorators and emitDecoratorMetadata within the tsconfig.json file.

"experimentalDecorators": true,        
"emitDecoratorMetadata": true, 

as per the invertsify documentation, we should also have the following tsconfig.json properties set

"target": "es5",
"lib": ["es6"],
"types": ["reflect-metadata"],
"module": "commonjs",
"moduleResolution": "node",

As is usual in C# (at least), the best way to work with IoC is to define an interface for our abstraction and then an implementation. However for inverisfy we also define a Symbol for the interfaces. So let’s assume we’re going to have a Service interface along with RestService and WebsocketService.

First create your Service.ts file and here’s a simple example

interface Service {
  call(data: string): void;
};

export default Service;

Now let’s create a couple of implementations, RestService.ts

import "reflect-metadata";
import Service from "./Service";
import { injectable } from "inversify";

@injectable()
class RestService implements Service {
  call(data: string): void {
    console.log("RestService called");
  }
}

export default RestService;

As you can see, we decorate the class with @injectable as this class may be injected into another class.

Here’s our WebsocketService.ts

import "reflect-metadata";
import Service from "./Service";
import { injectable } from "inversify";

@injectable()
class WebsocketService implements Service {
  call(data: string): void {
    console.log("WebsocketService called");
  }
}

export default WebsocketService;

Within the types.ts (below) we create the symbols (keys/identifiers) for use with our types.

const Types = {
  Service: Symbol.for("Service"),
  Application: Symbol.for("Application")
};

export default Types;

Here’s an Application interface Application.ts

interface Application {   
  run(): void;
}

export default Application;

MyApplication.ts

import "reflect-metadata";
import { inject, injectable } from "inversify";
import Application from "./Application";
import Types from "./types";
import Service from "./Service";

@injectable()
class MyApplication implements Application {
  private readonly service: Service;

  constructor(@inject(Types.Service) service) {
    this.service = service;
  }

  run(): void {        
    this.service.call("");
  }
}

export default MyApplication; 

In the above you can see we’re injecting (via the @inject decorator on the constructor) a type of symbol type Service. Hence this is where the server implementation will be injected into.

To supply inversify with the implementations for various types, we create the file inversify.config.ts. In the example file below we bind the symbol type/identifier with an implementation.

import { Container } from "inversify";
import Service from "./Service";
import RestService from "./RestService";
import Types from "./types";
import WebsocketService from "./WebsocketService";
import Application from "./Application";
import MyApplication from "./MyApplication";

const container = new Container();

//container.bind<Service>(Types.Service).to(RestService);
container.bind<Service>(Types.Service).to(WebsocketService);
container.bind<Application>(Types.Application).to(MyApplication);

export default container;

Finally, here’s an example implementation of the index.ts

import container from "./inversify.config";
import Application from "./Application";
import Types from "./types";

const application = container.get<Application>(Types.Application);
application.run();

There’s more to inversify than just the code listed above, such as you can have multiple Service implementations and use named bindings to receive the one you want and more.

JSON within subclasses, across multiple programming languages

I was developing an expression tree on a project, i.e. made up of subclasses of the class Expression, such as AndExpression, MemberExpression, LiteralExpression etc. The main code is TypeScript/JavaScript but this needs to pass JSON to TypeScript/JavaScript, C# or Java code (and possibly other languages).

Now when JavaScript JSON.stringify does it’s thing we’re left with no type information making it problematic converting each type back to it’s actual type, i.e. to an AndExpression not just an Expression.

A relatively easy way to solve this, whilst not as elegant as one might hope is to store a string representing the type within the object, for example

export class LiteralExpression extends Expression {
  public readonly $type: string = "LiteralExpression"
}

When we run the expression through JSON.stringify we get JSON with “$type”:”AndExpression” for example. In JavaScript we still need to do some work to convert this back to JavaScript classes, it’s easy enough to use JSON.parse(json) then iterate over our expression objects converting to subclasses and revive our objects from JSON in this way.

Note the use of the variable name $type. It’s important that it’s named $type if you want it to easily be translated into C# objects with Json.NET as this name is hard coded in this library, whereas Java’s jackson JAR allows us to easily change the name/key used.

Json.NET (Newtonsoft.Json)

Sadly we don’t quite get everything for free using Json.NET because it’s expecting C# style naming for classes, i.e. assembly/namespace etc. The easiest way to deal with this it to serialize/deserialize using our own SerializationBinder, for example

public static class Serialization
{
  public class KnownTypesBinder : ISerializationBinder
  {
    public IList<Type> KnownTypes { get; set; }

    public Type BindToType(string assemblyName, string typeName)
    {
      return KnownTypes.SingleOrDefault(t => t.Name == typeName);
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
      assemblyName = null;
      typeName = serializedType.Name;
    }
  }

  private static KnownTypesBinder knownTypesBinder = new KnownTypesBinder
  {
    KnownTypes = new List<Type>
    {
      typeof(AndExpression),
      typeof(BinaryExpression),
      typeof(LiteralExpression),
      typeof(LogicalExpression),
      typeof(MemberExpression),
      typeof(NotExpression),
      typeof(OperatorExpression),
      typeof(OrExpression)
    }
  };

  public static string Serialize(Expression expression)
  {
    var json = JsonConvert.SerializeObject(
      expression, 
      Formatting.None, 
      new JsonSerializerSettings
    {
      TypeNameHandling = TypeNameHandling.Objects,
      SerializationBinder = knownTypesBinder
    });
    return json;
  }

  public static Expression Deserialize(string json)
  {
    return JsonConvert.DeserializeObject<Expression>(
      json, 
      new JsonSerializerSettings
    {
      TypeNameHandling = TypeNameHandling.Objects,
      SerializationBinder = knownTypesBinder
    });
  }
}

Don’t forget you’ll also need to mark your properties and/or constructor parameters with [JsonProperty(“left”)] especially if you have situations where the names are keywords.

com.fasterxml.jackson.core

In Java we can add the following dependency to our pom.xml

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.10.0</version>
</dependency>

Now in our Expression base class we write the following

import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "$type")
public class Expression {
}

This tells jackson to include the type info using the keyword $type.

We also need to add the @JsonCreator annotation to each of our classes and each constructor parameter requires the following annotation @JsonProperty(“left”). Finally to serialize/deserialize we create an ObjectMapper to allow us to map our types to real objects using

package com.rbs.expressions;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;

public class Serialization {

  private static ObjectMapper createMapper() {
    ObjectMapper mapper = new ObjectMapper();

    mapper.registerSubtypes(
      new NamedType(AndExpression.class, "AndExpression"),
      new NamedType(BinaryExpression.class, "BinaryExpression"),
      new NamedType(OrExpression.class, "OrExpression"),
      new NamedType(LiteralExpression.class, "LiteralExpression"),
      new NamedType(LogicalExpression.class, "LogicalExpression"),
      new NamedType(MemberExpression.class, "MemberExpression"),
      new NamedType(NotExpression.class, "NotExpression"),
      new NamedType(OperatorExpression.class, "OperatorExpression")
    );

    return mapper;
  }

  public static String serialize(Expression expression) throws JsonProcessingException {
    return createMapper().writeValueAsString(expression);
  }

  public static Expression deserialize(String json) throws JsonProcessingException {
    return createMapper().readValue(json, Expression.class);
  }
}

Vue components

In a previous post we looked at creating a Vue application. Let’s now look a little more in depth by looking at creating Vue components.

Note: I will be using TypeScript and classes for this, so called “Class-Style component”.

A Vue component would be stored within a .vue file, hence MyComponent.vue for example. Vue components take the form of a template which is made up of HTML with embedded Vue values etc. Styles may also be defined within a style element which will hold standard CSS). Next up we’d have a script tag if our component does anything more than just being a template with or without styles.

Hence we might layout our component like this

<template>
  <div class="hello">
    <h1>{{ greeting }} World</h1>
  </div>
</template>

<style scoped>
h1 {
  color: red;
}
</style>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class MyComponent extends Vue {
  private greeting: string = 'Hello';
}
</script>

What we’ve done is create a template for our HTML which is ultimately a div with an h1 element with the text Hello World being displayed. Obviously the greeting part is supplied by the component as it’s wrapped in the {{ }} (Mustache) syntax.

Next we’ve got the style (these sections need not be in any specific order). We obviously don’t need a style nor script if no style or logic is required. However to demonstrate it’s usage we’ve got it here and style scoped to the component (i.e. not global). Ofcourse this will display our template text in H1 font and red text colour.

Now to the slightly more interesting bit. The script contains our code. First off we import the Component decorator and the Vue base class in the standard way.

Obviously as Vue uses the @Component decorators you’ll need the experimental features of TypeScript enabled, which is what the vue client did when creating our application.

As is pretty obvious, we derive our component from Vue and then implement data and methods. In this case we simply have a constant string with our greeting, before we make this editable, let’s look at how we render/use this component.

In our App.vue for example, we add the following to the app template, i.e.

<template>
  <div id="app">
      <MyComponent />
  </div>
</template>

The next bit is dependent upon whether you’re using a router or not. We need to register our component, so without a router our App.vue would contain the following script tag

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import MyComponent from './components/MyComponent.vue';

@Component({
  components: {
    MyComponent,
  },
})
export default class App extends Vue {}
</script>

If we’re using a router we probably be using views and hence would declare the following with the view (here’s an example view)

<template>
  <div class="home">
    <MyComponent />
  </div>
</template>

<script>
import MyComponent from '@/components/MyComponent.vue';

export default {
  name: 'home',
  components: {
    MyComponent,
  },
};
</script>

Adding properties

Now we’ve seen how to create a component we’ll want to extend it by adding properties (attributes in HTML terms). So for example, instead of fixing our greeting string to “Hello” we’ll let the user of our component set the greeting.

To do this we need to add the Prop decorator to the greeting string with MyComponent, i.e.

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';

@Component
export default class MyComponent extends Vue {
  @Prop() private greeting!: string;
}
</script>

and now from the code using MyComponent we would write

<MyComponent greeting="Hello" />

Adding methods/handlers

Let’s extend our component with a button which, when clicked, increments a counter. So our component script now looks like this

import { Component, Vue, Prop } from 'vue-property-decorator';

@Component
export default class MyComponent extends Vue {
  private count: number = 0;

  @Prop() private greeting: string = 'Hello';

  handleClick(): void {
    this.count = this.count + 1;
  }
}

Now our template is changed to this

<template>
  <div class="hello">
    <h1>{{ greeting }} World</h1>
    <button @click="handleClick">Click</button>
    <h1>{{ count }}</h1>
  </div>
</template>

Note: We can use the @click or v-on:click – the @ is just a shorthand for v-on: in this instance.

Minimal Vue and beyond

Vue gives us the ability to include it in a a minimal way by adding a simple script dependency (or installing it into your project’s node_modules using yarn add vue). Vue also comes with a CLI (vue-cli) for building application from a scaffolding application.

Let’s start at the simplest level and create a basic HTML page (no bundling, no built-in web server, nothing) and start writing Vue code. Create an index.html file

<!DOCTYPE html>
<head>
  <!-- development version -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- production version
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  -->
</head>
<html>
  <body>
  </body>
</html>

The development version of Vue comes with console warnings etc. whereas the production version is optimized.

Let’s now place the following into the body tag

<div id="app">
  <button v-on:click="clicked">{{ message }}</button>    
  <div>{{ count }}</div>
</div>

<script>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello World',
    count: 0
  },
  methods: {
    clicked: function(event) {
      this.count++
    }
  }
})
</script>

What we’ve done is create the root (app) div, which corresponds to the el within the Vue options. Hence that Vue object is bound to the app element. It includes data in the form custom data, in this case a message (the usual Hello World example) but also a counter in the form of the count variable. The Vue options also include methods, in this case one labelled clicked is used in the button within the HTML.

Notice this use of this. to access the count in the method.

Now, in the HTML we use v- prefixed attributes to bind the elements to our Vue object (data and methods). So the button is bound to the v-on:click which in turn is assigned the method clicked as created in the Vue options.

Notice also the usage of the {{ }} (Mustache syntax) to allow us to inject (in this case) Vue data into the HTML.

As stated, there’s no web server or the likes, so we can now just drop this index.html into our chosen webserver and serve up Vue enabled web pages.

Taking it to the next step

In the previous example we use the Vue script from a CDN, but we can also run

yarn add vue

To include vue within the node_nodules of an application/website. Obviously this would be the route taken for anything more than the trivial example (above).

We’re not going to do anything more with this simple approach for building a Vue applications, however it does demonstrate that you can build a Vue application from scratch, choosing our preferred bundler etc. ourselves if required.

vue-cli

Let’s turn our attention now to creating a Vue application via the vue-cli tool.

So we’ve seen a minimal Vue page and we’ve seen we can bring Vue into our application in a way that allows us to pick and choose our technologies. With vue-cli we instead generate an application with all the “standard” pieces (i.e. bundler, webserver etc.).

Start by installing the vue-cli using

yarn global add @vue/cli

To check all went well, just run

vue --version

To create a project we simply run

vue create my-project

Obviously replacing my-project with your project name.

You will now be prompted to answer a couple of questions, for example

  • Please pick a preset
  • Pick the package manager to use when installing dependencies

See https://cli.vuejs.org/guide/creating-a-project.html#vue-create for a far more complete look at this stage.

If you simply choose the defaults you get bable, eslint and yarn configurations which is not actually what I wanted for this project.

So for the first prompt (Please pick a preset), I selected Manually select features and selected TypeScript, Router, Linter and Unit Testing, I then end up with further prompts asking whether I want class style components etc.

You’ll get the idea, vue-cli gives you default options all along the way.

Note: You can have vue-cli save your presets within ~/.vuerc or on Windows %USERPROFILE%/.vuerc, the option to save the presets is at the end of the available options for configuring your project.

If you prefer a UI to configure things with, then vue also comes with vue ui which will run a webapp (by default on port 8000). I’ll leave the reader to investigate the options themselves.

Once you’re happy with your configurations and you’ve generated your application, cd into your new project folder (cd my-project in case) and then run

yarn serve

This will start-up a server (by default on port 8080).

If we take a look at the code generated, you’ll notice we’ve moved far beyond the minimal use of Vue. I won’t cover too much here as really the topics around the generated code requires a post of their own, but suffice to say I’ve added a router (via the configuration selector). Vue creates main.ts which basically starts everything and mounts #app, which is within the new file type App.vue. The .vue files, I suppose are a little analogous to React’s JSX files in that they contain code and HTML, although obviously somewhat differently to JSX.

I tend to think of React as code with HTML/tags embedded in it (or returned from it) whereas Vue is more like markup with code embedded within it (similar to JSP, ASP etc. in that respect).

So just quickly looking at the generated Home.vue file (as stated, we’ll cover these more in another post). We have the following

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue';

export default {
  name: 'home',
  components: {
    HelloWorld,
  },
};
</script>

This is pretty easy to understand, like ASP.NET of old, we’re creating templates for our HTML which may also contain Vue code (as per our original minimal index.html). So the template can be thought of as our HTML component, then the script contains the code associated with that template (ofcourse you might simply have a template if no code is required). In this script we’re really just hosting the HelloWorld.vue component, passing props to it in the form of the msg=”Welcome to Your Vue.js App”.

Note: There are different ways to create components, we’ll look at in other posts, for now we’ll simply assume the above is the usual layout of our Vue components.

Vue with Visual Code

I tend to use Visual Code for most of my web development, for Vue it’s worth installing the Vetur plugin which gives Vue tooling for VS Code. This includes syntax highlighting, auto-complete, linting etc.

Note: The vue-cli also included a script to run linting across your code if you want to run that in a shell.

Redux actions and reducers

We tend to split our redux code into two “sections”, an action function and a reducer function which usually uses a switch to then return state based upon the supplied action.

Actions

An action can be thought of (within Redux) as a message or something that happens (hence an action). We might write an action creator as a function, like the following

export const onLoad = (name: string) => {
  return {
    type: ActionType.Load,
    payload: name
  };
};

this returns the action which has a shape of

{ type, payload } 

The type is required (as this is what we switch in the reducer) but the payload might not be, depending upon the action.

Alternatively we might dispatch an action using the redux store, for example

store.dispatch({ type: ActionType.Load, payload: name });

The key thing when creating actions is that they should not change anything but should simply state that some action should be taken and pass any data required within the reducer.

Note: the payload can be of more complex types, usually the type is simply a string representing the name of the action.

Reducers

Reducers responds to our action messages. The usual way to write a reducer is to have a function like the following

export default (state: any = initialState, action): any => {
  switch (action.type) {
    case ActionType.Load:
      return {
        ...state,
        queryName: action.payload
      };
    // ...
  }
  return state;
}

So we simply switch, based upon the action type (hence we’d usually have the action type string as a const, which must be unique across all your application reducers, hence a style such as the following is not unusual, where we prefix the action type value with some form of namespace followed by the action name

export enum ActionType {
   Load = "myapp/load",
   // ...
}

We can clone and add different values to the state using either the spread operator, i.e.

{ ...state, queryName: action.payload }

or via

Object.assign({}, state, { queryName: action.payload }); 

Rules for reducers

  1. Must always return the state even if no changes are made an even if the state is null but must never return undefined.
  2. Treat state as immutable, hence do not change state but simply return new state (which might be cloned and with changes from the previous state).
  3. A reducer should process every action even if it just simply returns the original state.

How to target the browsers we want to support

When developing a public facing web application we will usually want to try to be compatible with as large an audience and hence as large a selection of browsers (and their versions) as possible. Even within a private/intranet web site we’ll want to set some compatibility level to work with.

To that end, a useful addition to eslint is the eslint-plugin-compat plugin eslint-plugin-compat plugin.

yarn add eslint-plugin-compat -D

As per the documentation we should add the following to the .eslintrc.json file

{
  "extends": ["plugin:compat/recommended"],
  "env": {
    "browser": true
  },
  // ...
}

and within the package.json file we add the browserslist array, the following is an example of a possible setup

{
  "browserslist": [
    "> 0.2%", 
     "not dead",
    "not ie <= 11",
    "not op_mini all"  
  ]
}

The values within browserslist allow us to create a query that can reduce/increase the number and types or browsers supported as we wish.

For example the above suggests we want to support all browsers with more than 0.2% global usage statistics, where the data for this is taken from browserl.ist. This site also allows us to type these browserslist values into the edit box (removing quotes and new lines), i.e.

> 0.2%, last 2 versions, not dead, not op_mini all

Clicking Show Browsers will list the browsers that fall within the query range.

We can also execute the following command from our shell/terminal

npx browserslist "> 0.2%, last 2 versions, not dead, not op_mini all"

and this will also show you the browser that match that query also.

React context (developing a ThemeProvider)

I’ve been looking into theming a React project and whilst I ultimately intended to use the theming capabilities within material-ui I was interested in how I might write our own.

We’re going to be using React context.

Let’s start by creating a theme.ts file which will include our “base” theme style

export const theme = {
  button: {
    backgroundColor: "white",
    borderColor: "red",
    color: "blue",
    borderWidth: "2px",
    borderStyle: "solid",
    padding: "10px",
    fontSize: "24px",
  }
};

In the above code we created a button property which obviously defines our (rather horrible) default button style. Now we need some way to apply this theme (and any new version of our theme) to our application.

Hence we create a ThemeProvider (ThemeProvider.tsx in my case), which looks like this

import React from "react";
import { theme } from "../theme";

export const ThemeContext = React.createContext(theme);

export function ThemeProvider(props: any) {
  return (
    <ThemeContext.Provider value={props.theme}>
      {props.children}
    </ThemeContext.Provider>
  );
}

In this case, we create a React context, and assign a default value to it (in the shape of our base theme). The ThemeProvider function is then used to wrap our application supplying the theme to all components that wish to use it. So here’s an example of the ThemeProvider in use (in the App.tsx)

import React from 'react';
import { ThemeProvider } from './components/ThemeProvider';
import { Button } from './components/Button';
import { myTheme } from './myTheme';

const App: React.FC = () => {
  return (
    <ThemeProvider theme={myTheme}>
      <div className="App">
        <Button>Themed Button</Button>
      </div>
    </ThemeProvider>
  );
}

export default App;

You’ll notice we’ve also taken this opportunity to supply our overridden theme (with a slightly nicer button style) which is shown below (myTheme.ts)

export const myTheme = {
  button: {
    backgroundColor: "green",
    color: "white",
    borderWidth: "2px",
    borderStyle: "solid",
    padding: "10px",
    fontSize: "24px",
  }
};

As you can see from our App.tsx code, we’re using a Button component, so let’s look at that code now (Button.tsx)

import React from "react";
import { ThemeContext } from "./ThemeProvider";

export const Button = (props: any) => (
  <ThemeContext.Consumer>
    {theme => (
      <button style={theme.button} {...props}>
        {props.children}
      </button>
    )}
  </ThemeContext.Consumer>
);

In this code we consume the React context we created via the ThemeProvider file and apply the style to the button, also passing through any props to the button.

Now if you were to run this application the button will be displayed with our new theme (a nice green background button). If you change the App.tsx theme property to the default “base” theme, then we our default style.

CSS calc, you little beauty

When you have something like a React/material-ui appbar and maybe toolbars these would usually by set to a pixel height which is great, until we want to then expand a component beneath them and have it fill the available space ?

CSS calc() is here to save the day.

Here’s an example style in material-ui style code. In this code our appbar and toolbar’s combined height is 123px and we want the next component to fill the “container”. The following therefore calculates the available space by subtracting 123px from whatever 100% is.

const styles = (_theme: Theme) => ({
  container: {
    width: '100%',
    height: 'calc(100% - 123px)'
  },
});

Obviously we need to wrap our parent component in the withStyles function, i.e.

export withStyles(styles)(MyComponent);

then in the render method

const { classes } = this.props as any;
// ...
<div className={classes.container}>
// component to fill this space
</div>