scripts / setup.js
// scripts/setup.js
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
const PLUGIN_DIR = path.join(__dirname, '..');
const VENDOR_DIR = path.join(PLUGIN_DIR, "vendor");
const REPO_DIR = path.join(VENDOR_DIR, "tradingview-mcp");
const VENV_DIR = path.join(VENDOR_DIR, "venv");
const IS_WIN = process.platform === "win32";
const PYTHON_BIN = IS_WIN ? path.join(VENV_DIR, "Scripts", "python.exe") : path.join(VENV_DIR, "bin", "python");
const PIP_BIN = IS_WIN ? path.join(VENV_DIR, "Scripts", "pip.exe") : path.join(VENV_DIR, "bin", "pip");
function runCommand(command, args, options = {}) {
return new Promise((resolve, reject) => {
console.log(`\x1b[36m[Setup]\x1b[0m > ${command} ${args.join(' ')}`);
const child = spawn(command, args, { ...options, stdio: 'inherit' });
child.on("close", (code) => {
if (code === 0) resolve();
else reject(new Error(`Command failed with exit code ${code}`));
});
child.on("error", reject);
});
}
async function setup() {
console.log("\x1b[32m[Setup]\x1b[0m Initializing tradingview-mcp environment...");
if (!fs.existsSync(VENDOR_DIR)) fs.mkdirSync(VENDOR_DIR, { recursive: true });
// 1. Clone 或更新原始碼
if (!fs.existsSync(REPO_DIR)) {
console.log("\x1b[32m[Setup]\x1b[0m Cloning tradingview-mcp repository...");
await runCommand("git", ["clone", "https://github.com/atilaahmettaner/tradingview-mcp", REPO_DIR]);
} else {
console.log("\x1b[32m[Setup]\x1b[0m Repository exists. Pulling latest changes...");
try { await runCommand("git", ["-C", REPO_DIR, "pull"]); } catch (e) {}
}
// 2. 建立 Python venv
if (!fs.existsSync(VENV_DIR)) {
console.log("\x1b[32m[Setup]\x1b[0m Creating Python virtual environment...");
const pythonCmd = IS_WIN ? "python" : "python3";
await runCommand(pythonCmd, ["-m", "venv", VENV_DIR]);
}
// 3. 安裝 Python 套件
console.log("\x1b[32m[Setup]\x1b[0m Installing Python dependencies (this may take a few minutes)...");
await runCommand(PYTHON_BIN, ["-m", "pip", "install", "--upgrade", "pip"]);
// 使用 -e (editable mode) 安裝,確保 pyproject.toml 中的 scripts 入口點被正確建立
await runCommand(PIP_BIN, ["install", "-e", "."], { cwd: REPO_DIR });
console.log("\x1b[32m[Setup]\x1b[0m Setup complete!");
}
setup().catch(err => {
console.error("\x1b[31m[Setup Error]\x1b[0m", err.message);
console.error("Please ensure Python 3.10+ and Git are installed and available in your system PATH.");
process.exit(1);
});
scripts / setup.js
// scripts/setup.js
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
const PLUGIN_DIR = path.join(__dirname, '..');
const VENDOR_DIR = path.join(PLUGIN_DIR, "vendor");
const REPO_DIR = path.join(VENDOR_DIR, "tradingview-mcp");
const VENV_DIR = path.join(VENDOR_DIR, "venv");
const IS_WIN = process.platform === "win32";
const PYTHON_BIN = IS_WIN ? path.join(VENV_DIR, "Scripts", "python.exe") : path.join(VENV_DIR, "bin", "python");
const PIP_BIN = IS_WIN ? path.join(VENV_DIR, "Scripts", "pip.exe") : path.join(VENV_DIR, "bin", "pip");
function runCommand(command, args, options = {}) {
return new Promise((resolve, reject) => {
console.log(`\x1b[36m[Setup]\x1b[0m > ${command} ${args.join(' ')}`);
const child = spawn(command, args, { ...options, stdio: 'inherit' });
child.on("close", (code) => {
if (code === 0) resolve();
else reject(new Error(`Command failed with exit code ${code}`));
});
child.on("error", reject);
});
}
async function setup() {
console.log("\x1b[32m[Setup]\x1b[0m Initializing tradingview-mcp environment...");
if (!fs.existsSync(VENDOR_DIR)) fs.mkdirSync(VENDOR_DIR, { recursive: true });
// 1. Clone 或更新原始碼
if (!fs.existsSync(REPO_DIR)) {
console.log("\x1b[32m[Setup]\x1b[0m Cloning tradingview-mcp repository...");
await runCommand("git", ["clone", "https://github.com/atilaahmettaner/tradingview-mcp", REPO_DIR]);
} else {
console.log("\x1b[32m[Setup]\x1b[0m Repository exists. Pulling latest changes...");
try { await runCommand("git", ["-C", REPO_DIR, "pull"]); } catch (e) {}
}
// 2. 建立 Python venv
if (!fs.existsSync(VENV_DIR)) {
console.log("\x1b[32m[Setup]\x1b[0m Creating Python virtual environment...");
const pythonCmd = IS_WIN ? "python" : "python3";
await runCommand(pythonCmd, ["-m", "venv", VENV_DIR]);
}
// 3. 安裝 Python 套件
console.log("\x1b[32m[Setup]\x1b[0m Installing Python dependencies (this may take a few minutes)...");
await runCommand(PYTHON_BIN, ["-m", "pip", "install", "--upgrade", "pip"]);
// 使用 -e (editable mode) 安裝,確保 pyproject.toml 中的 scripts 入口點被正確建立
await runCommand(PIP_BIN, ["install", "-e", "."], { cwd: REPO_DIR });
console.log("\x1b[32m[Setup]\x1b[0m Setup complete!");
}
setup().catch(err => {
console.error("\x1b[31m[Setup Error]\x1b[0m", err.message);
console.error("Please ensure Python 3.10+ and Git are installed and available in your system PATH.");
process.exit(1);
});