feat(deploy): build nfc-pcsc's native pcsclite addon for Electron (mkAtmApp)

Rebuild @pokusew/pcsclite (V8 C++ addon) against Electron headers like
better-sqlite3, and package nfc-pcsc + @pokusew/pcsclite into the runtime
node_modules. Its binding.gyp hardcodes Debian /usr/include/PCSC + /usr/lib,
so point the compiler/linker at nixpkgs pcsclite via CPATH/LIBRARY_PATH
(winscard.h lives under include/PCSC); pcsclite.lib in buildInputs lets
autoPatchelf wire libpcsclite.so.1 into the .node RPATH. Bumps the pnpmDeps
hash for the added nfc-pcsc dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-08-05 04:55:30 +02:00
commit 51dcf0d6f6

View file

@ -38,7 +38,7 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
inherit (finalAttrs) pname version src pnpmWorkspaces;
inherit pnpm;
fetcherVersion = 3;
hash = "sha256-03ANBQ7bHJwsqlX2ScA1+1LFuO8njiuU7O4VGOb6cMM=";
hash = "sha256-XqpQpFL3PqnFltb4ujAmmnnV0LOqTHKV/bo3riFu9pY=";
};
nativeBuildInputs = [
@ -57,6 +57,11 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
pkgs.sqlite.dev # better-sqlite3
pkgs.libudev-zero # serialport
pkgs.stdenv.cc.cc.lib # libstdc++
# @pokusew/pcsclite (nfc-pcsc): the `lib` output carries libpcsclite.so so
# autoPatchelf wires it into the .node RPATH at runtime. Compile/link paths
# are injected via CPATH/LIBRARY_PATH in buildPhase (its binding.gyp
# hardcodes Debian /usr paths instead of using pkg-config).
pkgs.pcsclite.lib
];
env = {
@ -83,6 +88,19 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
--arch=x64
popd
# @pokusew/pcsclite (nfc-pcsc's native addon) — also V8 C++ API, so it too
# must be rebuilt against Electron's headers. Its binding.gyp hardcodes
# /usr/include/PCSC + /usr/lib, so point the compiler/linker at nixpkgs'
# pcsclite explicitly (winscard.h lives under include/PCSC).
echo "=== Rebuilding @pokusew/pcsclite against Electron ${electron.version} headers ==="
pushd node_modules/.pnpm/@pokusew+pcsclite@*/node_modules/@pokusew/pcsclite
CPATH="${pkgs.pcsclite.dev}/include/PCSC''${CPATH:+:$CPATH}" \
LIBRARY_PATH="${pkgs.pcsclite.lib}/lib''${LIBRARY_PATH:+:$LIBRARY_PATH}" \
HOME=$TMPDIR ${nodejs}/bin/npx --yes node-gyp rebuild \
--nodedir="$electron_nodedir" \
--arch=x64
popd
# Build the Electron app (turbo builds all workspace deps + app)
pnpm --filter="@bitSpire/machine..." build
@ -95,7 +113,7 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
installPhase = ''
runHook preInstall
mkdir -p $out/node_modules/{@lamassu,@serialport}
mkdir -p $out/node_modules/{@lamassu,@serialport,@pokusew}
# Helper: find a package dir inside the pnpm virtual store.
# pnpm store dirs look like: node_modules/.pnpm/<name>@<ver>[_<peer-suffix>]/node_modules/<name>
@ -132,6 +150,12 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
copy_pnpm_pkg bindings $out/node_modules/bindings
copy_pnpm_pkg file-uri-to-path $out/node_modules/file-uri-to-path
# nfc-pcsc + @pokusew/pcsclite (Bolt Card reader). The compiled
# pcsclite.node (from the rebuild above) rides along in the package dir and
# loads via `bindings` (already copied). autoPatchelf wires libpcsclite.
copy_pnpm_pkg nfc-pcsc $out/node_modules/nfc-pcsc
copy_pnpm_pkg @pokusew/pcsclite $out/node_modules/@pokusew/pcsclite
# @bitSpire/hal (workspace package, dynamically imported for hardware access)
mkdir -p $out/node_modules/@bitSpire/hal/dist
cp -rL packages/hal/dist/* $out/node_modules/@bitSpire/hal/dist/