Electron Adventures: Episode 3: What Can Backend Code Even Do?
Tags: javascript, electron
Published: 2021-07-27 20:07:42

Let's do something that frontend code can't do on its own - run shell commands.

### Run a single command

Electron on the backend is basically node process, with some extras for communicating with the browser.

Now it would much prefer you to use complicated async system with proper error handling and so on, but we don't need this complexity - we'll just use `child_process.execSync` to run a command and capture its output.

We need to do two small things with the result. First we need to convert `Buffer` into `String` - this isn't done automatically, as the output could be some binary like an image, not a valid UTF-8 String. And then we'll trim extra newline.

```javascript
let child_process = require("child_process")

let runCommand = (command) => {
  return child_process.execSync(command).toString().trim()
}
```

### Gather information about operating system

Let's run a bunch of random commands to get system information

```javascript
let sysInfo = {
  os: runCommand("uname -s"),
  cpu: runCommand("uname -m"),
  hostname: runCommand("hostname -s"),
  ip: runCommand("ipconfig getifaddr en0"),
}
```

### Ship this information to the frontend

We can now ship this information to the frontend. There are many more complex ways, and we'll absolutely get there, but for now, let's jut use the simplest one and pass a query string.

Weirdly Javascript still doesn't have a way to turn an `Object` into a query string, so we'll need to roll our own!

```javascript
let toQueryString = (obj) => {
  let q = []
  for (let key in obj) {
    q.push(`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
  }
  return q.join("&")
}
```

We used `loadFile` function before, but that doesn't have any easy way of passing an query string. But we can do a little trick, and use `loadURL` with `file:` protocol instead.

```javascript
let { app, BrowserWindow } = require("electron")

function createWindow() {
  let win = new BrowserWindow({})
  win.maximize()
  win.loadURL(`file:${__dirname}/index.html?${toQueryString(sysInfo)}`)
}

app.on("ready", createWindow)

app.on("window-all-closed", () => {
  app.quit()
})
```

### Parse this on the frontend

Javascript has a way to parse a query string, but it's not very convenient. But let's give it a go the hard way with just browser APIs:

```javascript
let data = new URLSearchParams(document.location.search)

let info = document.querySelector("#info")

for (const [key, value] of data) {
  let p = document.createElement("p")
  p.append(`${key} = ${value}`)
  info.append(p)
}
```

We absolutely do not want to be writing bigger apps this way of course, so we'll get to using libraries soon.

For now let's just add this simple HTML, and we have a simple app:

```html
<!DOCTYPE html>
<html>
  <body>
    <h1>System information!</h1>
    <div id="info"></div>
    <script src="app.js"></script>
  </body>
</html>
```

### The result

And here's what we got:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heb5nag7ffedrsx6tdzm.png)

[All the code for the episode is here](https://github.com/taw/electron-adventures/tree/master/episode-03-what-can-backend-code-even-do).

See you in the next episode!