Jack Stephens
Jack Stephens' Latest Blog

Jack Stephens' Latest Blog

FrakenApp #1: Part 4, Temporary Node Server

Jack Stephens's photo
Jack Stephens
·Feb 2, 2022·

4 min read

Major Oversight

In part 3, I continued to use TCP Server Simulator even though it is a big black box that requires Windows. This post is not a step-by-step; it is more of a "What I did."

Simple TCP Repeater

I wrote a simple NodeJS app that repeats whatever you send to it. It is straightforward, so that I will include it here:

// # ip address for the socket
const HOST: string = 'localhost'; 
// # port number for the socket
const PORT: number = 3001; 


// TypeScript types (just for fun)
type ServerType = {
    listen: (port: number, host: string, callback: { (): void; }) => void; 
};
type SocketType = { 
    setKeepAlive: (enable: boolean, initialDelay: number) => void; 
    on: (event: string, callback: {(dataBuffer: ArrayBuffer): void;}) => void; 
    write: (data: string) => void; 
};
type NetType = {
    createServer: (callback: { (socket: SocketType): void; }) => ServerType; 
};

const net: NetType = require('net');

const server: ServerType = net.createServer(function(socket: SocketType){
    // Phone Home App can phone at any time
    socket.setKeepAlive(true, 60000);

    // Listen for data 
    socket.on('data', function(dataBuffer: ArrayBuffer) {
        const data: string = dataBuffer + ''; // Change ArrayBuffer to string
        console.log(data);
        // Later on,  I want to be able to kill off Phone Home App
        if (data.trim().toLocaleLowerCase() === 'bye'){
            socket.write('hangup');
        }
        else {
            socket.write('You said "' + data + '"');
        }
    });
});

server.listen(PORT, HOST, function() {
    console.log("listening on " + PORT);
});

(I did start to play with TypeScript here)

Launching Client and Server Together

It is cool that the Server (Simple TCP Repeater) is now our code. It is cool that the code isn't platform-specific. But it would be cool if we could launch the client and server with a single command. This is where things got tricky.

I moved Phone Home App down one directory level and Simple TCP Repeater into a single NPM project. Then I fiddled with configurations to build and launch both apps together.

package.json

I combined all the dependencies from both projects and put them at the project's root.

Launching with npm run start

Concurrently Package

I found a project that allows me to run multiple commands concurrently. I need to do this so I can run both processes simultaneously; otherwise, if I launch Simple TCP Repeater then Phone Home App, NPM would wait for the Simple TCP Repeater to end before continuing. You can install Concurrently with this command:

npm i concurrently --save-dev

And you can run it like this:

"something": "concurrently --kill-others \"npm run first\" \"npm run second\""

Edit scripts section of package.json

I changed the sections to look like this:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc --build ./simple-tcp-repeater/tsconfig.json && tsc -build ./phone-home-electron/tsconfig.json",
    "server": "node simple-tcp-repeater/index.js",
    "client": "electron ./phone-home-electron/.",
    "start": "npm run build && concurrently --kill-others \"npm run server\" \"npm run client\""
  },

Here I broke the "start" command into parts:

  • "build" compiles both project's TypeScript files (I have to compile them separately because of how I wrote the TypeScript,
  • "server" launches Simple TCP Repeater (notice that this one is first),
  • "client" launches Phone Home App &
  • "start" brings it all together with the concurrently package. build is before concurrently because we need to build before we can launch.

Launching with the VSCode Debugger

I changed .vscode/launch.json to look like this:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Server",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/simple-tcp-repeater/index.js",
      "preLaunchTask": "tsc: build - simple-tcp-repeater/tsconfig.json",
      "outFiles": ["${workspaceFolder}/simple-tcp-repeater/**/*.js"],
    },
    {
      "name": "Client",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}/phone-home-electron",
      "preLaunchTask": "tsc: build - phone-home-electron/tsconfig.json",
      "outFiles": ["${workspaceFolder}/phone-home-electron/**/*.js"],
      "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron .",
      "windows": {
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
      },
      "args" : ["."],
      "outputCapture": "std"
    }
  ],
  "compounds": [
    {
      "name": "Server/Client",
      "configurations": ["Server", "Client"]
    }
  ]
}

This sets up three debug configurations: one for just the Server (Simple TCP Repeater), one for just the Client (Phone Home App), and one for both as Server/Client. 04-vscode-choose-debug.PNG

And It Runs on the Mac

I cloned the project from GitHub on the Mac, and I could get it to run the first time! ep-4-on-the-mac.jpg

Progress in the FrakenApp #1 project

What I have

  • An Electron app that can communicate with a .NET app (which we didn't even have to write).
  • We can control the Electron app from the .NET app (send the command "hangup," and the Electron app closes).
  • The app now uses TypeScript, sort of. We have a build process that transforms the TypeScript to JavaScript (and doing almost nothing else for us yet).
  • I touched the Mac. Phone Home App ran there on my first try.

What's still missing

  • No Oracle (this may have been a big mistake).
  • Not using NET Core (or even .NET Framework at this point).
  • Not using strict TypeScript.
  • Using JQuery, not React.js.
  • Not building the Electron App; I'm running it from VS Code.
  • TCP Server app is temporary; it needs to use .NET Core.

The Code

The code is available on my GitHub as Frakenapp-01 or the Release for this article.

 
Share this