feat: arduino-install 脚本执行时自动检查本地cli状态

This commit is contained in:
王立帮
2025-05-09 21:20:41 +08:00
parent db2ef2a22b
commit a166170d02

View File

@@ -10,90 +10,158 @@ import * as tar from 'tar';
import shell from 'shelljs'; import shell from 'shelljs';
const version = '1.2.2'; const CLI_VERSION = '1.0.0';
const ARDUINO_AVR_VERSION = '1.8.6';
const ARDUINO_ESP8266_VERSION = '3.1.1';
const ARDUINO_ESP32_VERSION = '2.0.15';
const CLI_DIR_PATH = path.resolve(process.cwd(), 'arduino-cli');
function getPlatformTarget() { class ArduinoCLI {
const platform = os.platform(); static getDonwloadUrl(version) {
const arch = os.arch(); const platform = os.platform();
if (platform === 'win32') { const arch = os.arch();
return arch === 'x64' ? 'arduino-cli_' + version + '_Windows_64bit.zip' : null; let filename = '';
} if (platform === 'win32') {
if (platform === 'darwin') { if (arch === 'x64') {
return 'arduino-cli_' + version + '_macOS_64bit.tar.gz'; filename = `arduino-cli_${version}_Windows_64bit.zip`;
} } else if (arch === 'ia32') {
if (platform === 'linux') { filename = `arduino-cli_${version}_Windows_32bit.zip`;
if (arch === 'x64') return 'arduino-cli_' + version + '_Linux_64bit.tar.gz'; }
if (arch === 'arm64') return 'arduino-cli_' + version + '_Linux_ARM64.tar.gz'; } else if (platform === 'darwin') {
if (arch.startsWith('arm')) return 'arduino-cli_' + version + '_Linux_ARMv7.tar.gz'; if (arch === 'x64') {
} filename = `arduino-cli_${version}_macOS_64bit.tar.gz`;
return null; } else if (arch === 'arm64') {
} filename = `arduino-cli_${version}_macOS_ARM64.tar.gz`;
}
async function arduinoInstall() { } else if (platform === 'linux') {
const filename = getPlatformTarget(); if (arch === 'x64') {
if (!filename) { filename = `arduino-cli_${version}_Linux_64bit.tar.gz`;
console.error('当前系统或架构不受支持'); } else if (arch === 'ia32') {
return; filename = `arduino-cli_${version}_Linux_32bit.tar.gz`;
} else if (arch === 'arm64') {
filename = `arduino-cli_${version}_Linux_ARM64.tar.gz`;
} else if (arch === 'arm') {
const { stdout } = shell.exec('uname -m', { silent: true });
if (stdout === 'armv6l') {
filename = `arduino-cli_${version}_Linux_ARMv6.tar.gz`;
} else if (stdout === 'armv7l') {
filename = `arduino-cli_${version}_Linux_ARMv7.tar.gz`;
}
}
}
if (!filename) {
throw new Error('The current system or architecture is not supported');
}
return `https://downloads.arduino.cc/arduino-cli/${filename}`;
} }
const url = `https://downloads.arduino.cc/arduino-cli/${filename}`; #version_ = '';
#dirPath_ = '';
const temp = path.resolve(process.cwd(), 'temp'); #cliPath_ = '';
await fsExtra.ensureDir(temp); #configPath_ = '';
const dest = path.resolve(temp, filename); #tempPath_ = '';
const cliDirPath = path.resolve(process.cwd(), 'arduino-cli'); #boards_ = {};
await fsExtra.ensureDir(cliDirPath); constructor(version, dirPath) {
let cliPath = ''; this.#version_ = version;
if (os.platform() === 'win32') { this.#dirPath_ = dirPath;
cliPath = path.resolve(cliDirPath, 'arduino-cli.exe'); this.#tempPath_ = path.resolve(dirPath, 'temp');
} else { fsExtra.ensureDirSync(dirPath);
cliPath = path.resolve(cliDirPath, 'arduino-cli'); fsExtra.ensureDirSync(this.#tempPath_);
if (os.platform() === 'win32') {
this.#cliPath_ = path.resolve(dirPath, 'arduino-cli.exe');
} else {
this.#cliPath_ = path.resolve(dirPath, 'arduino-cli');
}
this.#configPath_ = path.resolve(dirPath, 'arduino-cli.json');
} }
const configPath = path.resolve(cliDirPath, 'arduino-cli.json');
const config = await fsExtra.readJson(path.resolve(process.cwd(), 'arduino-cli.json')); async init() {
config.directories = { const config = await fsExtra.readJson(path.resolve(process.cwd(), 'arduino-cli.json'));
data: path.resolve(cliDirPath, 'Arduino15'), config.directories = {
downloads: path.resolve(cliDirPath, 'staging'), data: path.resolve(this.#dirPath_, 'Arduino15'),
user: path.resolve(cliDirPath, 'Arduino') downloads: path.resolve(this.#dirPath_, 'staging'),
}; user: path.resolve(this.#dirPath_, 'Arduino')
await fsExtra.writeJson(configPath, config, { };
spaces: ' ' await fsExtra.writeJson(this.#configPath_, config, {
}); spaces: ' '
if (!fsPlus.isFileSync(cliPath)) { });
console.log(`开始下载: ${url}`); if (!this.available()) {
await this.install();
}
shell.exec(`"${this.#cliPath_}" core update-index --config-file "${this.#configPath_}"`);
this.updateBoardsStatus();
}
updateBoardsStatus() {
const { stdout } = shell.exec(`"${this.#cliPath_}" core list --json --config-file "${this.#configPath_}"`, {
silent: true
});
const info = JSON.parse(stdout);
const { platforms } = info;
this.#boards_ = {};
for (let board of platforms) {
this.#boards_[board.id] = board.installed_version;
}
}
available() {
let available = false;
if (fsPlus.isFileSync(this.#cliPath_)) {
const { stdout } = shell.exec(`"${this.#cliPath_}" version --json --config-file "${this.#configPath_}"`, {
silent: true
});
const info = JSON.parse(stdout);
if (info.VersionString === this.#version_) {
available = true;
}
}
return available;
}
async coreInstall(boardKey, version) {
if (this.#boards_[boardKey] === version) {
console.log(`Platform ${boardKey}@${version} already installed`);
return;
}
shell.exec(`"${this.#cliPath_}" core install ${boardKey}@${version} --config-file "${this.#configPath_}"`);
}
async install() {
const url = ArduinoCLI.getDonwloadUrl(this.#version_);
console.log(`Start Download: ${url}`);
const res = await fetch(url); const res = await fetch(url);
if (!res.ok) throw new Error(`下载失败: ${res.statusText}`); if (!res.ok) {
const fileStream = fs.createWriteStream(dest); throw new Error(`Download failed: ${res.statusText}`);
}
const cliTempPath = path.resolve(this.#tempPath_, path.basename(url));
const fileStream = fs.createWriteStream(cliTempPath);
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
res.body.pipe(fileStream); res.body.pipe(fileStream);
res.body.on('error', reject); res.body.on('error', reject);
fileStream.on('finish', resolve); fileStream.on('finish', resolve);
}); });
console.log('下载完成,开始解压...'); console.log('Download complete, start to unzip...');
if (filename.endsWith('.zip')) { if (url.endsWith('.zip')) {
await decompress(dest, cliDirPath, { await decompress(cliTempPath, this.#dirPath_, {
plugins: [decompressUnzip()] plugins: [decompressUnzip()]
}); });
} else { } else {
await tar.x({ await tar.x({
file: dest, file: cliTempPath,
cwd: cliDirPath, cwd: this.#dirPath_,
strict: true strict: true
}); });
} }
fs.unlinkSync(dest); fs.unlinkSync(cliTempPath);
console.log('解压完成,arduino-cli可执行文件已准备好'); console.log('Unzip successfully, the arduino-cli is ready');
} }
shell.exec(`"${cliPath}" core update-index --config-file "${configPath}"`);
console.log('\n开始下载: Arduino AVR');
shell.exec(`"${cliPath}" core install arduino:avr@1.8.6 --config-file "${configPath}"`);
console.log('\n开始下载: Arduino ESP8266');
shell.exec(`"${cliPath}" core install esp8266:esp8266@3.1.1 --config-file "${configPath}"`);
console.log('\n开始下载: Arduino ESP32');
shell.exec(`"${cliPath}" core install esp32:esp32@2.0.15 --config-file "${configPath}"`);
} }
await arduinoInstall();
const arduino = new ArduinoCLI(CLI_VERSION, CLI_DIR_PATH);
await arduino.init();
arduino.coreInstall('arduino:avr', ARDUINO_AVR_VERSION);
arduino.coreInstall('esp8266:esp8266', ARDUINO_ESP8266_VERSION);
arduino.coreInstall('esp32:esp32', ARDUINO_ESP32_VERSION);