# Submit Your Service to Commandeer

To build out Commandeer, we are using a common toolset of Vue and Typescript. We have included a startup example service, that shows you how to integrate your own service or one of your choosing into Commandeer. You can simply send us a PR request with a new service, and we will look to pipeline it into the system.

To help explain how you can create a service to implement some bit of functionality into the Commandeer system, we would like you to put on your imagination caps, and follow along with our example below.

# Tank Service

As one of the generals in the army, you, my friend have been tasked with integrating your tank management system into Commandeer. To do this, you say, great, I am going to write a nice common framework on the Commandeer Open repository, so people from the ships team, and the castles team can someday integrate their services in as well.

# Folder Structure

/tank-service
  App.vue
  main.ts
  package.json
  router.ts
  store.ts
  /tanks
    /components
      TankComponent.vue
      TankPage.vue
    /types
      index.ts
      ITank.ts
      ITankState.ts
      TankType.ts
    tank.ts
    tanks.json
    tankService.ts
    tankStore.ts
/serverless
  /tank-dynamo-stream-event
    package.json
    tankDynamoStreamEvent.ts
    tankDynamoStreamEvent.yml
    yarn.lock
  /tank-s3-file-created-event
    package.json
    tankS3FileCreatedEvent.ts
    tankS3FileCreatedEvent.yml
         yarn.lock
  /tank-sqs-message-received-event
    package.json
    tankSqsMessageReceivedEvent.ts
    tankSqsMessageReceivedEvent.yml
    yarn.lock
/terraform
  tank-created-sqs-queue.tf
  tank-history-s3-bucket.tf
  tank-dynamo-table.tf
  tank-s3-bucket.tf

# Test Data

tanks.json - sample tanks

[
  {
    "name": "British Mark 1",
    "tankType": "HEAVY"
  },
  {
    "name": "Tank, Medium Mark A",
    "tankType": "MEDIUM"
  },
  {
    "name": "Renault FT",
    "tankType": "LIGHT"
  },
  {
    "name": "Char 2C",
    "tankType": "SUPER_HEAVY"
  },
  {
    "name": "PT-76",
    "tankType": "LIGHT"
  },
  {
    "name": "FV101 Scorpion",
    "tankType": "LIGHT"
  },
  {
    "name": "FV107 Scimitar",
    "tankType": "LIGHT"
  }
]

# Interfaces and Enumerations

ITank.ts

import { TankType } from './TankType';

export interface ITank {
  id?: string;
  name?: string;
  tankType?: TankType;
}

TankStatus.ts - Status of a tank - OPERATIONAL, INOPERABLE, RETIRED

/**
* @description - current status of the tank
*   OPERATIONAL - tank is oiled and gassed up and ready to roll
*   INOPERABLE - tank is broken and should be fixed soon
*   RETIRED - tank is ready for the museum
*/
export enum TankStatus {
  OPERATIONAL = 'OPERATIONAL',
  INOPERABLE = 'INOPERABLE',
  RETIRED = 'RETIRED',
}

TankType.ts - Type of tank - LIGHT, MEDIUM, HEAVY, SUPER_HEAVY

export enum TankType {
  LIGHT = 'LIGHT',
  MEDIUM = 'MEDIUM',
  HEAVY = 'HEAVY',
  SUPER_HEAVY = 'SUPER_HEAVY',
}

# Service and Models

tank.ts - tank object class. This implements the ITank interface.

import { v4 as uuid } from 'uuid';
import { ITank, TankType } from './types';

const tankSample: ITank = {
  name: 'USS Destroyer',
};

export class Tank implements ITank {

  public id?: string;
  public name?: string;
  public tankType: TankType = TankType.LIGHT;

  public constructor(tank: ITank = tankSample) {
    this.id = (tank.id)
      ? tank.id
      : uuid();

    this.name = tank.name;

    if (tank.tankType) {
      this.tankType = tank.tankType;
    }
  }

}

tankService.ts - Service class that handles all interactions with some sort of data source. In this example, we are simply loading data from the tanks.json file, but you might implement a more robust solution that handles API calls. Remember, Commandeer runs within Electron, so you can do sophisticated local caching and have full access to the filesystem which can be very helpful.

import { Tank } from './tank';

const tanksLocal = require(`./tanks.json`);

export class TankService {

  private static _tanks: Tank[] = [];

  public static async clearCache(): Promise {
    try {
      this._tanks = [];
    } catch (ex) {
      throw ex;
    }
  }

  public static getTanks(): Tank[] {
    // if already cached, return the tanks
    if (this._tanks && this._tanks.length) {
      return this._tanks;
    }

    // save the json tanks file to the local _tanks array
    this._tanks = tanksLocal.map(t => {
      return new Tank(t);
    });

    return this._tanks;
  }

}

# Vue.js Vuetify Components and Vuex Store

tankStore.ts - The Vuex store is where we handle state. In this case, we are storing tanks to show on the UI.

TankComponent.vue - Holds the details about a tank. This should be able to be used for all CRUD operations.

TankPage.vue - This is a table of tanks that you can click on to view a specific tank. You usually have a refresh button, add button, and possibly a region scanner, so you can see if you have tanks anywhere else in the world.