From 825105c22852059850ff8a788aa6aed7d80ccb37 Mon Sep 17 00:00:00 2001 From: Andrey Parfenov Date: Sat, 28 Feb 2026 11:58:26 +0100 Subject: [PATCH] Fix Node.js library path resolution for packaged Electron apps --- nodejs_package/brainflow/board_shim.ts | 5 +++-- nodejs_package/brainflow/data_filter.ts | 5 +++-- nodejs_package/brainflow/lib_path.ts | 28 +++++++++++++++++++++++++ nodejs_package/brainflow/ml_model.ts | 3 ++- 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 nodejs_package/brainflow/lib_path.ts diff --git a/nodejs_package/brainflow/board_shim.ts b/nodejs_package/brainflow/board_shim.ts index 37447b1dc..2a94e924e 100644 --- a/nodejs_package/brainflow/board_shim.ts +++ b/nodejs_package/brainflow/board_shim.ts @@ -12,6 +12,7 @@ import { LogLevels, } from './brainflow.types'; import {BoardControllerCLikeFunctions as CLike, BoardControllerFunctions} from './functions.types'; +import {resolveLibPath} from './lib_path'; export class BrainFlowInputParams { @@ -60,7 +61,7 @@ class BoardControllerDLL extends BoardControllerFunctions private constructor() { super (); - this.libPath = `${__dirname}/../brainflow/lib`; + this.libPath = resolveLibPath(); this.dllPath = this.getDLLPath(); this.lib = this.getLib(); @@ -705,4 +706,4 @@ export class BoardShim } return JSON.parse(out[0].substring(0, len[0])); } -} \ No newline at end of file +} diff --git a/nodejs_package/brainflow/data_filter.ts b/nodejs_package/brainflow/data_filter.ts index 8ae4fa43d..66ea6a94d 100644 --- a/nodejs_package/brainflow/data_filter.ts +++ b/nodejs_package/brainflow/data_filter.ts @@ -19,6 +19,7 @@ import { } from './brainflow.types'; import {complex} from './complex'; import {DataHandlerCLikeFunctions as CLike, DataHandlerFunctions} from './functions.types'; +import {resolveLibPath} from './lib_path'; class DataHandlerDLL extends DataHandlerFunctions { @@ -32,7 +33,7 @@ class DataHandlerDLL extends DataHandlerFunctions private constructor() { super (); - this.libPath = `${__dirname}/../brainflow/lib`; + this.libPath = resolveLibPath(); this.dllPath = this.getDLLPath(); this.lib = this.getLib(); @@ -606,4 +607,4 @@ export class DataFilter } return output[0]; } -} \ No newline at end of file +} diff --git a/nodejs_package/brainflow/lib_path.ts b/nodejs_package/brainflow/lib_path.ts new file mode 100644 index 000000000..a5d93b1dc --- /dev/null +++ b/nodejs_package/brainflow/lib_path.ts @@ -0,0 +1,28 @@ +import fs from 'fs'; +import path from 'path'; + +const appAsarRegexp = new RegExp(`\\${path.sep}app\\.asar\\${path.sep}`, 'g'); + +export function resolveLibPath(): string +{ + const defaultLibPath = path.resolve(__dirname, '..', 'brainflow', 'lib'); + const electronProcess = process as NodeJS.Process & {resourcesPath?: string}; + const searchRoots = [ + __dirname, + __dirname.replace(appAsarRegexp, `${path.sep}app.asar.unpacked${path.sep}`), + typeof electronProcess.resourcesPath === 'string' ? electronProcess.resourcesPath : '', + ].filter(Boolean); + + const libPathCandidates = [ + defaultLibPath, + ...searchRoots.flatMap((root) => [ + path.resolve(root, '..', 'brainflow', 'lib'), + path.resolve(root, '..', 'node_modules', 'brainflow', 'brainflow', 'lib'), + path.resolve(root, 'node_modules', 'brainflow', 'brainflow', 'lib'), + path.resolve(root, 'app.asar.unpacked', 'node_modules', 'brainflow', 'brainflow', 'lib'), + ]), + ]; + + const existingPath = libPathCandidates.find((candidate) => fs.existsSync(candidate)); + return existingPath || defaultLibPath; +} diff --git a/nodejs_package/brainflow/ml_model.ts b/nodejs_package/brainflow/ml_model.ts index 7676780fd..a2d07552b 100644 --- a/nodejs_package/brainflow/ml_model.ts +++ b/nodejs_package/brainflow/ml_model.ts @@ -11,6 +11,7 @@ import { LogLevels, } from './brainflow.types'; import {MLModuleCLikeFunctions as CLike, MLModuleFunctions} from './functions.types'; +import {resolveLibPath} from './lib_path'; export class BrainFlowModelParams { @@ -52,7 +53,7 @@ class MLModuleDLL extends MLModuleFunctions private constructor() { super (); - this.libPath = `${__dirname}/../brainflow/lib`; + this.libPath = resolveLibPath(); this.dllPath = this.getDLLPath(); this.lib = this.getLib();