UNPKG

@writeshh/nepse-sdk

Version:

Node.js wrapper around NepseUnofficialApi (Python)

109 lines (98 loc) 3.92 kB
#!/usr/bin/env node /* Ensures Python (>=3.11) is available and installs NepseUnofficialApi. - Prefers pip for the current python3 - Falls back to pipx if available */ const { execSync } = require('node:child_process'); const fs = require('node:fs'); const path = require('node:path'); function run(cmd) { try { return execSync(cmd, { stdio: 'pipe' }).toString().trim(); } catch (err) { return null; } } function has(cmd) { return !!run(`command -v ${cmd}`); } function ensurePython() { const py = has('python3') ? 'python3' : has('python') ? 'python' : null; if (!py) { console.error('[nepse-node] Python 3.11+ not found. Please install Python >=3.11'); process.exit(0); // do not hard-fail install } const ver = run(`${py} -c "import sys; print('.'.join(map(str, sys.version_info[:3])))"`); if (!ver) return py; const [maj, min] = ver.split('.').map(Number); if (maj < 3 || (maj === 3 && min < 11)) { console.warn(`[nepse-node] Detected Python ${ver}. NepseUnofficialApi requires >=3.11. You may encounter issues.`); } return py; } function ensurePackage(py) { // Prefer an isolated virtualenv inside the package to avoid PEP 668 issues const projectRoot = path.resolve(__dirname, '..'); const venvDir = path.join(projectRoot, '.venv'); const isWin = process.platform === 'win32'; const venvPython = isWin ? path.join(venvDir, 'Scripts', 'python.exe') : path.join(venvDir, 'bin', 'python'); const venvPip = isWin ? path.join(venvDir, 'Scripts', 'pip.exe') : path.join(venvDir, 'bin', 'pip'); try { if (!fs.existsSync(venvPython)) { console.log('[nepse-node] Creating virtual environment for Python dependencies'); execSync(`${py} -m venv ${JSON.stringify(venvDir)}`, { stdio: 'inherit' }); } } catch (e) { console.warn('[nepse-node] Failed to create venv, will try system pip. Error:', e.message); } function isNepseInstalled(pythonPath) { const out = run(`${pythonPath} -c "import importlib, sys; sys.exit(0 if importlib.util.find_spec('nepse') else 1)"`); return out !== null; } // Try venv first if (fs.existsSync(venvPython)) { if (!isNepseInstalled(venvPython)) { try { // Try upgrading pip first execSync(`${JSON.stringify(venvPython)} -m pip install --upgrade pip`, { stdio: 'inherit' }); } catch (_) {} try { execSync(`${JSON.stringify(venvPip)} install --quiet git+https://github.com/basic-bgnr/NepseUnofficialApi`, { stdio: 'inherit' }); } catch (e1) { console.warn('[nepse-node] venv pip install failed, retrying with break-system-packages'); try { execSync(`${JSON.stringify(venvPip)} install --quiet --break-system-packages git+https://github.com/basic-bgnr/NepseUnofficialApi`, { stdio: 'inherit' }); } catch (e2) { console.warn('[nepse-node] venv pip install still failed:', e2.message); } } } // Record the venv python path for the bridge try { const hintFile = path.join(projectRoot, 'bridge', '.python_path'); fs.writeFileSync(hintFile, venvPython, 'utf8'); } catch {} if (isNepseInstalled(venvPython)) return; } // Fallback to system pip/pipx const pip = has('pip3') ? 'pip3' : has('pip') ? 'pip' : null; if (pip) { try { execSync(`${pip} install --user --quiet git+https://github.com/basic-bgnr/NepseUnofficialApi`, { stdio: 'inherit' }); return; } catch (_) {} } if (has('pipx')) { try { execSync(`pipx install git+https://github.com/basic-bgnr/NepseUnofficialApi`, { stdio: 'inherit' }); return; } catch (_) {} } console.warn('[nepse-node] Failed to auto-install NepseUnofficialApi. Please install manually:\n pip3 install --user git+https://github.com/basic-bgnr/NepseUnofficialApi'); } (function main() { const py = ensurePython(); if (!py) return; ensurePackage(py); })();