167 lines
5.9 KiB
JavaScript
Executable File
167 lines
5.9 KiB
JavaScript
Executable File
import os from 'node:os';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import fsExtra from 'fs-extra';
|
|
import fsPlus from 'fs-plus';
|
|
import fetch from 'node-fetch';
|
|
import decompress from 'decompress';
|
|
import decompressUnzip from 'decompress-unzip';
|
|
import * as tar from 'tar';
|
|
import shell from 'shelljs';
|
|
|
|
|
|
const CLI_VERSION = '1.3.1';
|
|
const ARDUINO_AVR_VERSION = '1.8.6';
|
|
const ARDUINO_ESP8266_VERSION = '3.1.1';
|
|
const ARDUINO_ESP32_VERSION = '2.0.15-cn';
|
|
const CLI_DIR_PATH = path.resolve(process.cwd(), 'arduino-cli');
|
|
|
|
|
|
class ArduinoCLI {
|
|
static getDonwloadUrl(version) {
|
|
const platform = os.platform();
|
|
const arch = os.arch();
|
|
let filename = '';
|
|
if (platform === 'win32') {
|
|
if (arch === 'x64') {
|
|
filename = `arduino-cli_${version}_Windows_64bit.zip`;
|
|
} else if (arch === 'ia32') {
|
|
filename = `arduino-cli_${version}_Windows_32bit.zip`;
|
|
}
|
|
} else if (platform === 'darwin') {
|
|
if (arch === 'x64') {
|
|
filename = `arduino-cli_${version}_macOS_64bit.tar.gz`;
|
|
} else if (arch === 'arm64') {
|
|
filename = `arduino-cli_${version}_macOS_ARM64.tar.gz`;
|
|
}
|
|
} else if (platform === 'linux') {
|
|
if (arch === 'x64') {
|
|
filename = `arduino-cli_${version}_Linux_64bit.tar.gz`;
|
|
} else if (arch === 'ia32') {
|
|
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}`;
|
|
}
|
|
|
|
#version_ = '';
|
|
#dirPath_ = '';
|
|
#cliPath_ = '';
|
|
#configPath_ = '';
|
|
#tempPath_ = '';
|
|
#boards_ = {};
|
|
constructor(version, dirPath) {
|
|
this.#version_ = version;
|
|
this.#dirPath_ = dirPath;
|
|
this.#tempPath_ = path.resolve(dirPath, 'temp');
|
|
fsExtra.ensureDirSync(dirPath);
|
|
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');
|
|
}
|
|
|
|
async init() {
|
|
const config = await fsExtra.readJson(path.resolve(process.cwd(), 'arduino-cli.json'));
|
|
config.directories = {
|
|
data: path.resolve(this.#dirPath_, 'Arduino15'),
|
|
downloads: path.resolve(this.#dirPath_, 'staging'),
|
|
user: path.resolve(this.#dirPath_, 'Arduino')
|
|
};
|
|
await fsExtra.writeJson(this.#configPath_, config, {
|
|
spaces: ' '
|
|
});
|
|
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);
|
|
if (!res.ok) {
|
|
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) => {
|
|
res.body.pipe(fileStream);
|
|
res.body.on('error', reject);
|
|
fileStream.on('finish', resolve);
|
|
});
|
|
|
|
console.log('Download complete, start to unzip...');
|
|
if (url.endsWith('.zip')) {
|
|
await decompress(cliTempPath, this.#dirPath_, {
|
|
plugins: [decompressUnzip()]
|
|
});
|
|
} else {
|
|
await tar.x({
|
|
file: cliTempPath,
|
|
cwd: this.#dirPath_,
|
|
strict: true
|
|
});
|
|
}
|
|
fs.unlinkSync(cliTempPath);
|
|
console.log('Unzip successfully, the arduino-cli is ready');
|
|
}
|
|
}
|
|
|
|
|
|
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); |