()
| 85 | } |
| 86 | |
| 87 | export async function getNodeExecutable() { |
| 88 | if (cachedNodeExecutable) return cachedNodeExecutable |
| 89 | |
| 90 | for (const candidate of [ |
| 91 | getProcessEnvironmentVariable('HOWCODE_NODE_PATH'), |
| 92 | getProcessEnvironmentVariable('NODE'), |
| 93 | ]) { |
| 94 | const normalized = candidate?.trim() |
| 95 | if (normalized && isExecutableFile(normalized)) { |
| 96 | cachedNodeExecutable = normalized |
| 97 | return cachedNodeExecutable |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | const shellNode = await discoverNodeFromShell() |
| 102 | if (shellNode) { |
| 103 | cachedNodeExecutable = shellNode |
| 104 | return cachedNodeExecutable |
| 105 | } |
| 106 | |
| 107 | // Do not use Electron's process.execPath here: it would put native extensions back on the |
| 108 | // Electron ABI. If discovery reaches this fallback, spawn will fail with a clear host error. |
| 109 | cachedNodeExecutable = 'node' |
| 110 | return cachedNodeExecutable |
| 111 | } |
| 112 | |
| 113 | export function getElectronResourcesPath() { |
| 114 | const processWithResourcesPath = process as NodeJS.Process & { |
no test coverage detected