こんにちはジョージです。「私は FileMaker 開発者だから Node.js の事がよくわからなくて、”Node.js を知る” ために公式サイトをチェックしていたんだ。その途中で “Single Executable Applications” を知ったんだよ。」最近流行りの言い方だそうです。
Single Executable Applications とは
この機能を使用すると、Node.js がインストールされていないシステムに Node.js アプリケーションを簡単に配布できます。
https://nodejs.org/api/single-executable-applications.html
具体的には「Node.js で動作する “何か” を作ります。そしてこの機能を使って単一実行形式のファイルに変換します。そのファイルを配ります。カスタム App からファイルを実行します。」となると思うのですがイマイチ想像できませんよね。。。
今回は、QR コードを作成する Single Executable Applications を作成して、FileMaker Pro から実行してみましょう。
QR コードの作成
まずは QR コードを作成する Node.js プロジェクトを作成します。
/**
* Copyright © 2024 Genecom, Inc. All Rights Reserved.
*
* 汎用バーコード生成 プログラム
*
* @description node.js で .png 形式のバーコードを作成。
* @author Takeshi Yamamoto
* @version 1.0
* @since 2024/01/25
*/
/**
* コマンドライン引数 について
* https://github.com/tj/commander.js
*/
/**
* バーコード生成 について
* https://github.com/bwipp/postscriptbarcode/wiki/Options-Reference
*/
import fs from 'fs';
import bwipjs from 'bwip-js';
import { program } from "commander";
program
.requiredOption('-p, --path <path>', 'output path')
.option('-c, --contents <contents>', 'contents of barcode', '0123456789')
.option('-t, --type <type>', 'type of barcode', 'qrcode')
.option('-w, --width', 'barcode width', 24)
.option('-h, --height', 'barcode height', 24);
program.parse();
const options = program.opts();
bwipjs.toBuffer({
bcid: options.type, // Barcode type
text: options.contents, // Text to encode
scale: 1, // 3x scaling factor
includetext: true, // Show human-readable text
textxalign: 'center', // Always good to set this
width: options.width, // Bar width, in millimeters
height: options.height, // Bar height, in millimeters
paddingheight: 2,
paddingwidth: 2,
backgroundcolor: 'FFFFFF',
}, function (err, png) {
if (err) {
// Decide how to handle the error
// `err` may be a string or Error object
console.log(err.message);
} else {
// png.length : PNG file length
// png.readUInt32BE(16) : PNG image width
// png.readUInt32BE(20) : PNG image height
fs.writeFile(options.path, png, function(err) {
if(err) {
console.log(err.message);
}
console.log('done');
});
}
});
{
"dependencies": {
"bwip-js": "^4.2.0",
"commander": "^11.1.0",
"fs": "^0.0.1-security"
},
"type": "module" // ソースファイル拡張子を .mjs にするか、この 1 行を追記しないとエラー出力
}
実行します。
> node index.js -p hoge.png
無事に QR コードが作成できました。詳しくは bwipjs と commander モジュールを調べてね。
単一実行ファイルの作成準備
後はドキュメント通りにコマンドを実行していくだけなのですが 1 つ大きな制約がありました。import や require を使った Node.js プロジェクトはうまく変換できません。
The single executable application feature currently only supports running a single embedded script using the CommonJS module system.
単一実行可能アプリケーション機能は現在、CommonJS モジュール システムを使用した単一の埋め込みスクリプトの実行のみをサポートしています。
https://nodejs.org/api/single-executable-applications.html
ドキュメントを確認すると「単一の埋め込みスクリプト」である必要があるとの事なので、esbuild なるものをインストールして、利用しているモジュール含めひとつの js ファイルにまとめます。
./node_modules/.bin/esbuild index.js --bundle --outfile=out.js --platform=node
out.js にまとまりました!
単一実行ファイルの作成
私は Docker 上のコンテナに Node.js 環境があるので、以下の順番にコマンドを実行しました。
echo '{ "main": "out.js", "output": "sea-prep.blob" }' > sea-config.json
node --experimental-sea-config sea-config.json
cp $(command -v node) qrcode
npx postject qrcode NODE_SEA_BLOB sea-prep.blob \
--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
完成したバイナリを実行します。
./qrcode -p hoge.png
おぉ!QR コードが作成できました!
他の OS で単一実行ファイルの作成
Node.js が動作する他のプラットフォームにプロジェクトをコピーします。同じように順番にコマンドを実行します。今度は Windows 環境で単一実行ファイルの作成を行います。いくつかのコマンドが Windows 用になるので注意しましょう。
node -e "require('fs').copyFileSync(process.execPath, 'qrcode.exe')"
npx postject qrcode.exe NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
無事に単一バイナリファイルが作成できたようです。「あっ」というまに Linux, Windows 環境で実行可能な QR コード生成単一実行ファイルが完成しました。
できれば実行対象の OS をターゲットに単一実行ファイルが生成できればよいのですが、本機能はまだ実験段階らしいのでそこまで対応してないようです。(執筆時点)
ちなみに nexe というコマンドラインユーティリティを使うと、Node.js プロジェクトからターゲット OS を指定したバイナリが作成できますが、Node.js 公式の方法を試してみたかったのです。
FileMaker から QR コードを生成してみる
完成したバイナリを Windows 系 OS の FileMaker Server にコピーします。一度生成した単一実行ファイルは OS があっていればファイルをコピーするだけで他の PC からも利用可能です。そして BaseElements Plugin の BE_ExecuteSystemCommand を使えば、FileMaker Server が動作する OS レベルのコマンドを実行できるので「サーバ上のスクリプト実行」ステップ経由で QR コードを生成して、オブジェクトフィールドに格納してみます。
※ 最低限の動作確認ができればよいのでスクリプトはこんな感じです。
#
# PSOS
サーバー上のスクリプト実行 [ 指定: 一覧から ; 「Barcode-Windows」 ; 引数: "blog.genecom.co.jp" ; 終了するまで待つ: オン ]
変数を設定 [ $result ; 値: Get ( スクリプトの結果 ) ]
#
# QRコード生成
フィールド設定 [ qrcode::qrcode ; Base64Decode ( $result; qrcode::__PK_ID & ".png" ) ]
#
# ダイアログの表示
カスタムダイアログを表示 [ ReadQRCode ( qrcode::qrcode ) ]
#
#
#
#
#
#
# #
変数を設定 [ $param ; 値: Get( スクリプト引数 ) ]
#
# 出力パスを設定
BE_ExecuteSystemCommand 経由でスペースを含むパラメータが複数あると、うまく変換できないのでやむなく短い形式のパスを利用
変数を設定 [ $path ; 値: "c:\PROGRA~1\FileMaker\FILEMA~1\Data\Documents\fuga.png" ]
#
テキストを挿入 [ 選択 ; ターゲット: $cmd ; 「cmd /c """c:\Program Files\FileMaker\FileMaker Server\Data\Scripts\qrcode" -p "#path" -c "#param"""」 ]
変数を設定 [ $cmd ; 値: Substitute ( $cmd; [ "#path"; $path ]; [ "#param"; $param ] ) ]
#
# qrcode 生成
変数を設定 [ $r ; 値: BE_ExecuteSystemCommand( $cmd; 360) ]
#
変数を設定 [ $base64 ; 値: Base64EncodeRFC ( 4648; BE_FileImport ( $path ) ) ]
#
現在のスクリプト終了 [ テキスト結果: $base64 ]
#
#
#
#
#
スクリプト実行
早速スクリプトを実行してみます。うまく QR コードが生成されました。
まとめ
いかがでしたでしょうか ?今日は Node.js の Single Executable Applications 機能を使って QR コードを生成する単一実行形式のファイルを作成してみました。
Node.js では他にも便利なライブラリやモジュールが数多くあると思いますので FileMaker カスタム App からそれらを利用できれば強力なツールになると思います。興味のある方はぜひ試してみてくさい!