@paimaexample/npm-avail-light-client
Version:
A wrapper for the Avail Light Client CLI
174 lines (150 loc) • 5.32 kB
JavaScript
const os = require("os");
const fs = require("fs");
const path = require("path");
const { spawn } = require("child_process");
const tar = require("tar");
const extract = require("extract-zip");
const downloadLinks = {
"apple-arm64":
"https://github.com/availproject/avail-light/releases/download/avail-light-client-v1.13.0-rc10/avail-light-apple-arm64.tar.gz",
"apple-x86_64":
"https://github.com/availproject/avail-light/releases/download/avail-light-client-v1.13.0-rc10/avail-light-apple-x86_64.tar.gz",
"linux-amd64":
"https://github.com/availproject/avail-light/releases/download/avail-light-client-v1.13.0-rc10/avail-light-linux-amd64.tar.gz",
"windows-x86_64":
"https://github.com/availproject/avail-light/releases/download/avail-light-client-v1.13.0-rc10/avail-light-x86_64-pc-windows-msvc.exe.zip",
};
const getBinaryKey = () => {
const isLinux = os.platform() === "linux";
const isWindows = os.platform() === "win32";
const isApple = os.platform() === "darwin";
const isArm = os.arch() === "arm64";
const isX86 = os.arch() === "x64";
if (isLinux && isArm) {
throw new Error(
"Unsupported platform: Linux ARM64 is not supported for native binary.",
);
}
if (isLinux && isX86) return "linux-amd64";
if (isWindows && isX86) return "windows-x86_64";
if (isApple && isArm) return "apple-arm64";
if (isApple && isX86) return "apple-x86_64";
throw new Error("Unsupported platform");
};
const getBinaryLink = () => {
const key = getBinaryKey();
const binaryLink = downloadLinks[key];
if (!binaryLink) throw new Error("Unsupported platform " + key);
return binaryLink;
};
const getBinaryPath = () => {
const key = getBinaryKey();
const isWindows = key.startsWith("windows");
const exeName = isWindows ? "avail-light-client.exe" : "avail-light-client";
return path.join(__dirname, "bin", exeName);
};
const downloadBinary = async () => {
const binaryLink = getBinaryLink();
const key = getBinaryKey();
const binDir = path.join(__dirname, "bin");
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
const tempPath = path.join(__dirname, path.basename(binaryLink));
console.log(`Downloading binary from ${binaryLink}...`);
const response = await fetch(binaryLink);
if (!response.ok) {
throw new Error(`Failed to download binary: ${response.statusText}`);
}
const fileStream = fs.createWriteStream(tempPath);
await new Promise(async (resolve, reject) => {
try {
for await (const chunk of response.body) {
fileStream.write(chunk);
}
fileStream.end();
fileStream.on("finish", resolve);
fileStream.on("error", reject);
} catch (error) {
reject(error);
}
});
console.log("Extracting binary...");
if (binaryLink.endsWith(".zip")) {
await extract(tempPath, { dir: path.join(__dirname, "bin") });
const files = fs.readdirSync(path.join(__dirname, "bin"));
const exeFile = files.find((f) => f.endsWith(".exe"));
if (exeFile && exeFile !== "avail-light-client.exe") {
fs.renameSync(
path.join(__dirname, "bin", exeFile),
path.join(__dirname, "bin", "avail-light-client.exe"),
);
}
} else if (binaryLink.endsWith(".tar.gz")) {
console.log("Extracting tar.gz file...");
console.log(tempPath);
console.log(binDir);
await tar.x({
file: tempPath,
cwd: binDir,
}).catch((err) => {
throw new Error(`Failed to extract tar.gz file: ${err.message}`);
});
// Verify extraction was successful
const extractedFiles = fs.readdirSync(binDir);
console.log(extractedFiles);
if (extractedFiles.length === 0) {
throw new Error("No files were extracted from the tar.gz archive");
}
const binaryName = os.platform() === "win32"
? "avail-light-client.exe"
: "avail-light-client";
if (extractedFiles.length > 0 && extractedFiles[0] !== binaryName) {
fs.renameSync(
path.join(binDir, extractedFiles[0]),
path.join(binDir, binaryName),
);
}
// Ensure the binary exists
if (!fs.existsSync(path.join(binDir, binaryName))) {
throw new Error(
`Extracted files do not contain expected binary: ${binaryName}`,
);
}
}
console.log("Binary extracted successfully at " + binDir);
fs.unlinkSync(tempPath);
const binaryPath = getBinaryPath();
if (!fs.existsSync(binaryPath)) {
throw new Error(`Binary not found at expected path: ${binaryPath}`);
}
if (os.platform() !== "win32") {
fs.chmodSync(binaryPath, "755");
}
console.log("Binary ready at:", binaryPath);
return binaryPath;
};
const runBinary = (args) => {
const binaryPath = getBinaryPath();
if (!fs.existsSync(binaryPath)) {
throw new Error(
`Binary not found at path: ${binaryPath}. Please run downloadBinary first.`,
);
}
console.log("Running binary at:", binaryPath);
console.log("Args:", args);
console.log("CWD:", process.cwd());
const child = spawn(binaryPath, args, { stdio: "inherit" });
child.on("exit", (code) => {
if (code !== 0) {
console.error(`Binary process exited with code ${code}`);
}
});
};
module.exports = {
getBinaryKey,
getBinaryLink,
getBinaryPath,
downloadBinary,
runBinary,
};