Skip to content

SHA1 digest (NW.js)

Chung Leong edited this page Mar 25, 2024 · 6 revisions

In this example we're going to create an app that calculates SHA-1 digests of files, using a built-in function of Zig's standard library.

Creating the app

First, we'll create the basic skeleton:

mkdir sha1
cd sha1
npm init -y
npm install node-zigar
mkdir src zig

Create sha1.zig:

const std = @import("std");

pub fn sha1(bytes: []const u8) [std.crypto.hash.Sha1.digest_length * 2]u8 {
    var digest: [std.crypto.hash.Sha1.digest_length]u8 = undefined;
    std.crypto.hash.Sha1.hash(bytes, &digest, .{});
    return std.fmt.bytesToHex(digest, .lower);
}

Then index.js:

const { readFile } = require('fs/promises');
const { join } = require('path');
require('node-zigar/cjs');
const { sha1 } = require('./zig/sha1.zig');

const isMac = process.platform === 'darwin'

nw.Window.open('./src/index.html', { width: 800, height: 600 }, (browser) => {
  // handle menu click
  const onOpenClick = () => {
    const { window: { document } } = browser;
    const file = document.getElementById('file'); 
    const heading = document.getElementById('heading');
    file.onchange = async (evt) => {
      const { target: { files } } = evt;
      if (files.length > 0) {
        const [ file ] = files;
        const data = await readFile(file.path);
        const hash = sha1(data).string;
        heading.textContent = hash;
      }
    };
    file.click();
  };
  const onCloseClick = () => {
    browser.close();
  };
  // create menu bar
  const menuBar = new nw.Menu({ type: 'menubar' });
  const fileMenu = new nw.Menu();
  fileMenu.append(new nw.MenuItem({ label: 'Open', click: onOpenClick }));
  fileMenu.append(new nw.MenuItem({ type: 'separator' }));
  fileMenu.append(new nw.MenuItem({ label: (isMac) ? 'Close' : 'Quit', click: onCloseClick }));
  menuBar.append(new nw.MenuItem({ label: 'File', submenu: fileMenu }));
  browser.menu = menuBar;    
});

Then index.html:

<!DOCTYPE html>
<html>
<head>
  <title>SHA-1 Digest</title>
</head>
<body>
  <h2 id="heading">Use file menu to open a file</h2>
  <input id="file" type="file" style="visibility: hidden;">
</body>
</html>

Adjust main in package.json:

  "main": "src/index.js",

Now we're ready to test the app:

[NW.js directory]/nw .

Configuring the app for deployment

We're going to follow the same steps as described in the hello world tutorial. First, we'll alter the require statement so it references a node-zigar module instead of a Zig file:

const { sha1 } = require('../lib/sha1.zigar');

Then we add node-zigar.config.json to the app's root directory:

{
  "optimize": "ReleaseSmall",
  "sourceFiles": {
    "lib/sha1.zigar": "zig/sha1.zig"
  },
  "targets": [
    { "platform": "win32", "arch": "x64" },
    { "platform": "win32", "arch": "arm64" },
    { "platform": "win32", "arch": "ia32" },
    { "platform": "linux", "arch": "x64" },
    { "platform": "linux", "arch": "arm64" },
    { "platform": "darwin", "arch": "x64" },
    { "platform": "darwin", "arch": "arm64" }
  ]
}

We build the library files:

npx node-zigar build

At this point the app is ready to be packaged.

Clone this wiki locally