node-labstreaminglayer
Advanced tools
+85
-19
@@ -23,8 +23,8 @@ /** | ||
| * Supported platforms: | ||
| * - Windows: Uses lsl_amd64.dll (x64) or lsl_i386.dll (x86) | ||
| * - macOS: Uses lsl.dylib (universal binary for x64/ARM64) | ||
| * - Linux: Uses lsl.so (requires system installation) | ||
| * - Windows: Uses lsl_amd64.dll (x64/ARM64) or lsl_i386.dll (x86/ia32) | ||
| * - macOS: Uses liblsl.dylib (universal binary for x64/ARM64) | ||
| * - Linux: Uses liblsl.so | ||
| * | ||
| * This function is Electron-aware and will check multiple paths including: | ||
| * - Standard path in node_modules | ||
| * - Standard path in node_modules (for regular Node.js and development) | ||
| * - Unpacked path when in ASAR archive (Electron production) | ||
@@ -39,10 +39,27 @@ * - Electron resources path | ||
| const archName = arch(); | ||
| // Enhanced logging for debugging (only in development mode) | ||
| const isDev = process.env.NODE_ENV === 'development' || process.env.DEBUG_LSL; | ||
| if (isDev) { | ||
| console.log('[LSL] Platform:', platformName, 'Architecture:', archName); | ||
| console.log('[LSL] Module directory:', __dirname); | ||
| } | ||
| let libName; | ||
| if (platformName === 'win32') { | ||
| // Windows: Select DLL based on architecture | ||
| // x64 (64-bit) uses amd64, x86 (32-bit) uses i386 | ||
| libName = archName === 'x64' ? 'lsl_amd64.dll' : 'lsl_i386.dll'; | ||
| // x64 (64-bit) and arm64 use amd64, x86/ia32 (32-bit) uses i386 | ||
| // ARM64 Windows can run x64 binaries through emulation | ||
| if (archName === 'x64' || archName === 'arm64') { | ||
| libName = 'lsl_amd64.dll'; | ||
| } | ||
| else if (archName === 'ia32' || archName === 'x86') { | ||
| libName = 'lsl_i386.dll'; | ||
| } | ||
| else { | ||
| // Fallback to 64-bit for unknown architectures | ||
| console.warn(`[LSL] Unknown Windows architecture '${archName}', defaulting to x64 library`); | ||
| libName = 'lsl_amd64.dll'; | ||
| } | ||
| } | ||
| else if (platformName === 'darwin') { | ||
| // macOS: Use standard liblsl prefix (supports Intel x64) | ||
| // macOS: Use standard liblsl prefix (universal binary supports both Intel x64 and Apple Silicon ARM64) | ||
| libName = 'liblsl.dylib'; | ||
@@ -59,3 +76,4 @@ } | ||
| const possiblePaths = []; | ||
| // 1. Standard path (works in development and regular Node.js) | ||
| // 1. Standard path (works when installed via npm) | ||
| // From dist/lib/ we go up 2 levels to package root where prebuild/ is located | ||
| const standardPath = join(__dirname, '..', '..', 'prebuild', libName); | ||
@@ -65,5 +83,15 @@ possiblePaths.push(standardPath); | ||
| if (standardPath.includes('app.asar')) { | ||
| // Try the unpacked version (where native modules must be extracted) | ||
| const unpackedPath = standardPath.replace('app.asar', 'app.asar.unpacked'); | ||
| // Use word boundary regex replacement for safer ASAR unpacking | ||
| // This prevents replacing 'app.asar' in paths like 'myapp.asarfile' | ||
| const unpackedPath = standardPath.replace(/\bapp\.asar\b/, 'app.asar.unpacked'); | ||
| possiblePaths.push(unpackedPath); | ||
| // Also try with the more specific Electron build structure | ||
| // Some Electron apps may have different directory structures | ||
| if (__dirname.includes('app.asar')) { | ||
| const electronModulePath = __dirname.replace(/\bapp\.asar\b/, 'app.asar.unpacked'); | ||
| const electronLibPath = join(electronModulePath, '..', '..', 'prebuild', libName); | ||
| if (electronLibPath !== unpackedPath) { | ||
| possiblePaths.push(electronLibPath); | ||
| } | ||
| } | ||
| } | ||
@@ -75,6 +103,14 @@ // 3. Try Electron's resources path if available (production Electron) | ||
| const resourcesPath = process.resourcesPath; | ||
| possiblePaths.push(join(resourcesPath, 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| possiblePaths.push(join(resourcesPath, 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| // Try multiple possible locations under resources | ||
| const resourcesPaths = [ | ||
| // Most common: unpacked in app.asar.unpacked | ||
| join(resourcesPath, 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| // Alternative: direct in resources (less common) | ||
| join(resourcesPath, 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| // Some builds might have different structure | ||
| join(resourcesPath, 'app', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| ]; | ||
| possiblePaths.push(...resourcesPaths); | ||
| } | ||
| // 4. Check for Electron app path | ||
| // 4. Check for Electron app path (for main process) | ||
| // @ts-ignore - global.app is an Electron-specific property | ||
@@ -86,11 +122,36 @@ if (typeof global !== 'undefined' && global.app?.getPath) { | ||
| const exeDir = dirname(appPath); | ||
| // Common Electron build structure | ||
| possiblePaths.push(join(exeDir, 'resources', 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| // Alternative structure for some Electron builders | ||
| possiblePaths.push(join(exeDir, '..', 'Resources', 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| } | ||
| catch (e) { | ||
| // Ignore if not in Electron main process | ||
| // Ignore if not in Electron main process or if app is not available | ||
| if (isDev) { | ||
| console.log('[LSL] Could not get Electron app path:', e); | ||
| } | ||
| } | ||
| } | ||
| // 5. Development/source paths (useful during development) | ||
| if (isDev) { | ||
| // Try relative to source directory during development | ||
| const devPath = join(__dirname, '..', '..', '..', '..', 'prebuild', libName); | ||
| possiblePaths.push(devPath); | ||
| // Also try the source directory structure | ||
| const srcPath = join(__dirname.replace(/dist[\\\/]lib/, 'prebuild'), libName); | ||
| possiblePaths.push(srcPath); | ||
| } | ||
| // Remove duplicate paths to avoid redundant checks | ||
| const uniquePaths = [...new Set(possiblePaths)]; | ||
| // Log all paths being checked in debug mode | ||
| if (isDev) { | ||
| console.log('[LSL] Searching for library in:'); | ||
| uniquePaths.forEach(p => console.log(` - ${p}`)); | ||
| } | ||
| // Find the first existing path | ||
| for (const path of possiblePaths) { | ||
| for (const path of uniquePaths) { | ||
| if (existsSync(path)) { | ||
| if (isDev) { | ||
| console.log('[LSL] Found library at:', path); | ||
| } | ||
| return path; | ||
@@ -100,6 +161,11 @@ } | ||
| // If no path exists, throw an error with helpful information | ||
| throw new Error(`Failed to find LSL library '${libName}'. Searched paths:\n` + | ||
| possiblePaths.map(p => ` - ${p}`).join('\n') + | ||
| '\n\nFor Electron apps, ensure native modules are unpacked from ASAR.\n' + | ||
| 'See: https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules'); | ||
| throw new Error(`Failed to find LSL library '${libName}' for ${platformName}/${archName}.\n\n` + | ||
| `Searched paths:\n` + | ||
| uniquePaths.map(p => ` - ${p}`).join('\n') + | ||
| '\n\nTroubleshooting:\n' + | ||
| '1. For Electron apps, ensure native modules are unpacked from ASAR:\n' + | ||
| ' Add to package.json: "build": { "asarUnpack": ["**/node-labstreaminglayer/**"] }\n' + | ||
| '2. Verify the prebuild folder contains the native libraries\n' + | ||
| '3. Try setting NODE_ENV=development or DEBUG_LSL=true for detailed logging\n' + | ||
| '4. See: https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules'); | ||
| } | ||
@@ -106,0 +172,0 @@ // Load the LSL library using Koffi FFI |
+1
-1
| { | ||
| "name": "node-labstreaminglayer", | ||
| "version": "0.2.1", | ||
| "version": "0.2.2", | ||
| "description": "Node.js bindings for Lab Streaming Layer (LSL)", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
+93
-19
@@ -26,8 +26,8 @@ /** | ||
| * Supported platforms: | ||
| * - Windows: Uses lsl_amd64.dll (x64) or lsl_i386.dll (x86) | ||
| * - macOS: Uses lsl.dylib (universal binary for x64/ARM64) | ||
| * - Linux: Uses lsl.so (requires system installation) | ||
| * - Windows: Uses lsl_amd64.dll (x64/ARM64) or lsl_i386.dll (x86/ia32) | ||
| * - macOS: Uses liblsl.dylib (universal binary for x64/ARM64) | ||
| * - Linux: Uses liblsl.so | ||
| * | ||
| * This function is Electron-aware and will check multiple paths including: | ||
| * - Standard path in node_modules | ||
| * - Standard path in node_modules (for regular Node.js and development) | ||
| * - Unpacked path when in ASAR archive (Electron production) | ||
@@ -43,9 +43,25 @@ * - Electron resources path | ||
| // Enhanced logging for debugging (only in development mode) | ||
| const isDev = process.env.NODE_ENV === 'development' || process.env.DEBUG_LSL; | ||
| if (isDev) { | ||
| console.log('[LSL] Platform:', platformName, 'Architecture:', archName); | ||
| console.log('[LSL] Module directory:', __dirname); | ||
| } | ||
| let libName: string; | ||
| if (platformName === 'win32') { | ||
| // Windows: Select DLL based on architecture | ||
| // x64 (64-bit) uses amd64, x86 (32-bit) uses i386 | ||
| libName = archName === 'x64' ? 'lsl_amd64.dll' : 'lsl_i386.dll'; | ||
| // x64 (64-bit) and arm64 use amd64, x86/ia32 (32-bit) uses i386 | ||
| // ARM64 Windows can run x64 binaries through emulation | ||
| if (archName === 'x64' || archName === 'arm64') { | ||
| libName = 'lsl_amd64.dll'; | ||
| } else if (archName === 'ia32' || archName === 'x86') { | ||
| libName = 'lsl_i386.dll'; | ||
| } else { | ||
| // Fallback to 64-bit for unknown architectures | ||
| console.warn(`[LSL] Unknown Windows architecture '${archName}', defaulting to x64 library`); | ||
| libName = 'lsl_amd64.dll'; | ||
| } | ||
| } else if (platformName === 'darwin') { | ||
| // macOS: Use standard liblsl prefix (supports Intel x64) | ||
| // macOS: Use standard liblsl prefix (universal binary supports both Intel x64 and Apple Silicon ARM64) | ||
| libName = 'liblsl.dylib'; | ||
@@ -62,3 +78,4 @@ } else if (platformName === 'linux') { | ||
| // 1. Standard path (works in development and regular Node.js) | ||
| // 1. Standard path (works when installed via npm) | ||
| // From dist/lib/ we go up 2 levels to package root where prebuild/ is located | ||
| const standardPath = join(__dirname, '..', '..', 'prebuild', libName); | ||
@@ -69,5 +86,16 @@ possiblePaths.push(standardPath); | ||
| if (standardPath.includes('app.asar')) { | ||
| // Try the unpacked version (where native modules must be extracted) | ||
| const unpackedPath = standardPath.replace('app.asar', 'app.asar.unpacked'); | ||
| // Use word boundary regex replacement for safer ASAR unpacking | ||
| // This prevents replacing 'app.asar' in paths like 'myapp.asarfile' | ||
| const unpackedPath = standardPath.replace(/\bapp\.asar\b/, 'app.asar.unpacked'); | ||
| possiblePaths.push(unpackedPath); | ||
| // Also try with the more specific Electron build structure | ||
| // Some Electron apps may have different directory structures | ||
| if (__dirname.includes('app.asar')) { | ||
| const electronModulePath = __dirname.replace(/\bapp\.asar\b/, 'app.asar.unpacked'); | ||
| const electronLibPath = join(electronModulePath, '..', '..', 'prebuild', libName); | ||
| if (electronLibPath !== unpackedPath) { | ||
| possiblePaths.push(electronLibPath); | ||
| } | ||
| } | ||
| } | ||
@@ -80,7 +108,17 @@ | ||
| const resourcesPath = process.resourcesPath; | ||
| possiblePaths.push(join(resourcesPath, 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| possiblePaths.push(join(resourcesPath, 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| // Try multiple possible locations under resources | ||
| const resourcesPaths = [ | ||
| // Most common: unpacked in app.asar.unpacked | ||
| join(resourcesPath, 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| // Alternative: direct in resources (less common) | ||
| join(resourcesPath, 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| // Some builds might have different structure | ||
| join(resourcesPath, 'app', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName), | ||
| ]; | ||
| possiblePaths.push(...resourcesPaths); | ||
| } | ||
| // 4. Check for Electron app path | ||
| // 4. Check for Electron app path (for main process) | ||
| // @ts-ignore - global.app is an Electron-specific property | ||
@@ -92,11 +130,42 @@ if (typeof global !== 'undefined' && global.app?.getPath) { | ||
| const exeDir = dirname(appPath); | ||
| // Common Electron build structure | ||
| possiblePaths.push(join(exeDir, 'resources', 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| // Alternative structure for some Electron builders | ||
| possiblePaths.push(join(exeDir, '..', 'Resources', 'app.asar.unpacked', 'node_modules', 'node-labstreaminglayer', 'prebuild', libName)); | ||
| } catch (e) { | ||
| // Ignore if not in Electron main process | ||
| // Ignore if not in Electron main process or if app is not available | ||
| if (isDev) { | ||
| console.log('[LSL] Could not get Electron app path:', e); | ||
| } | ||
| } | ||
| } | ||
| // 5. Development/source paths (useful during development) | ||
| if (isDev) { | ||
| // Try relative to source directory during development | ||
| const devPath = join(__dirname, '..', '..', '..', '..', 'prebuild', libName); | ||
| possiblePaths.push(devPath); | ||
| // Also try the source directory structure | ||
| const srcPath = join(__dirname.replace(/dist[\\\/]lib/, 'prebuild'), libName); | ||
| possiblePaths.push(srcPath); | ||
| } | ||
| // Remove duplicate paths to avoid redundant checks | ||
| const uniquePaths = [...new Set(possiblePaths)]; | ||
| // Log all paths being checked in debug mode | ||
| if (isDev) { | ||
| console.log('[LSL] Searching for library in:'); | ||
| uniquePaths.forEach(p => console.log(` - ${p}`)); | ||
| } | ||
| // Find the first existing path | ||
| for (const path of possiblePaths) { | ||
| for (const path of uniquePaths) { | ||
| if (existsSync(path)) { | ||
| if (isDev) { | ||
| console.log('[LSL] Found library at:', path); | ||
| } | ||
| return path; | ||
@@ -108,6 +177,11 @@ } | ||
| throw new Error( | ||
| `Failed to find LSL library '${libName}'. Searched paths:\n` + | ||
| possiblePaths.map(p => ` - ${p}`).join('\n') + | ||
| '\n\nFor Electron apps, ensure native modules are unpacked from ASAR.\n' + | ||
| 'See: https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules' | ||
| `Failed to find LSL library '${libName}' for ${platformName}/${archName}.\n\n` + | ||
| `Searched paths:\n` + | ||
| uniquePaths.map(p => ` - ${p}`).join('\n') + | ||
| '\n\nTroubleshooting:\n' + | ||
| '1. For Electron apps, ensure native modules are unpacked from ASAR:\n' + | ||
| ' Add to package.json: "build": { "asarUnpack": ["**/node-labstreaminglayer/**"] }\n' + | ||
| '2. Verify the prebuild folder contains the native libraries\n' + | ||
| '3. Try setting NODE_ENV=development or DEBUG_LSL=true for detailed logging\n' + | ||
| '4. See: https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules' | ||
| ); | ||
@@ -114,0 +188,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
3483661
0.25%6154
2.16%9
80%