From e7db2a85739680496a97996b5b0569e4bf5f7190 Mon Sep 17 00:00:00 2001
From: GyDi <zzzgydi@gmail.com>
Date: Tue, 22 Nov 2022 20:44:44 +0800
Subject: [PATCH] chore: update check script

---
 scripts/check.mjs | 410 ++++++++++++++++++++--------------------------
 1 file changed, 175 insertions(+), 235 deletions(-)

diff --git a/scripts/check.mjs b/scripts/check.mjs
index f56b65d..cc7adba 100644
--- a/scripts/check.mjs
+++ b/scripts/check.mjs
@@ -8,181 +8,131 @@ import { execSync } from "child_process";
 
 const cwd = process.cwd();
 const TEMP_DIR = path.join(cwd, "node_modules/.verge");
-
 const FORCE = process.argv.includes("--force");
-const NO_META = process.argv.includes("--no-meta") || false;
+
+const SIDECAR_HOST = execSync("rustc -vV")
+  .toString()
+  .match(/(?<=host: ).+(?=\s*)/g)[0];
+
+/* ======= clash ======= */
+const CLASH_URL_PREFIX =
+  "https://github.com/Dreamacro/clash/releases/download/premium/";
+const CLASH_LATEST_DATE = "2022.08.26";
+
+const CLASH_MAP = {
+  "win32-x64": "clash-windows-amd64",
+  "darwin-x64": "clash-darwin-amd64",
+  "darwin-arm64": "clash-darwin-arm64",
+  "linux-x64": "clash-linux-amd64",
+  "linux-arm64": "clash-linux-armv8",
+};
+
+/* ======= clash meta ======= */
+const META_URL_PREFIX = `https://github.com/MetaCubeX/Clash.Meta/releases/download/`;
+const META_VERSION = "v1.13.2";
+
+const META_MAP = {
+  "win32-x64": "Clash.Meta-windows-amd64-compatible",
+  "darwin-x64": "Clash.Meta-darwin-amd64",
+  "darwin-arm64": "Clash.Meta-darwin-arm64",
+  "linux-x64": "Clash.Meta-linux-amd64-compatible",
+  "linux-arm64": "Clash.Meta-linux-arm64",
+};
 
 /**
- * get the correct clash release infomation
+ * check available
  */
-function resolveClash() {
-  const { platform, arch } = process;
-
-  const CLASH_URL_PREFIX =
-    "https://github.com/Dreamacro/clash/releases/download/premium/";
-  const CLASH_LATEST_DATE = "2022.08.26";
-
-  // todo
-  const map = {
-    "win32-x64": "clash-windows-amd64",
-    "darwin-x64": "clash-darwin-amd64",
-    "darwin-arm64": "clash-darwin-arm64",
-    "linux-x64": "clash-linux-amd64",
-    "linux-arm64": "clash-linux-armv8",
-  };
 
-  const name = map[`${platform}-${arch}`];
+const { platform, arch } = process;
+if (!CLASH_MAP[`${platform}-${arch}`]) {
+  throw new Error(`clash unsupport platform "${platform}-${arch}"`);
+}
+if (!META_MAP[`${platform}-${arch}`]) {
+  throw new Error(`clash meta unsupport platform "${platform}-${arch}"`);
+}
 
-  if (!name) {
-    throw new Error(`unsupport platform "${platform}-${arch}"`);
-  }
+function clash() {
+  const name = CLASH_MAP[`${platform}-${arch}`];
 
   const isWin = platform === "win32";
-  const zip = isWin ? "zip" : "gz";
-  const url = `${CLASH_URL_PREFIX}${name}-${CLASH_LATEST_DATE}.${zip}`;
-  const exefile = `${name}${isWin ? ".exe" : ""}`;
-  const zipfile = `${name}.${zip}`;
-
-  return { url, zip, exefile, zipfile };
-}
-
-/**
- * get the correct Clash.Meta release infomation
- */
-async function resolveClashMeta() {
-  const { platform, arch } = process;
-
-  const urlPrefix = `https://github.com/MetaCubeX/Clash.Meta/releases/download/`;
-  const latestVersion = "v1.13.2";
-
-  const map = {
-    "win32-x64": "Clash.Meta-windows-amd64-compatible",
-    "darwin-x64": "Clash.Meta-darwin-amd64",
-    "darwin-arm64": "Clash.Meta-darwin-arm64",
-    "linux-x64": "Clash.Meta-linux-amd64-compatible",
-    "linux-arm64": "Clash.Meta-linux-arm64",
+  const urlExt = isWin ? "zip" : "gz";
+  const downloadURL = `${CLASH_URL_PREFIX}${name}-${CLASH_LATEST_DATE}.${urlExt}`;
+  const exeFile = `${name}${isWin ? ".exe" : ""}`;
+  const zipFile = `${name}.${urlExt}`;
+
+  return {
+    name: "clash",
+    targetFile: `clash-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
+    exeFile,
+    zipFile,
+    downloadURL,
   };
+}
 
-  const name = map[`${platform}-${arch}`];
-
-  if (!name) {
-    throw new Error(`unsupport platform "${platform}-${arch}"`);
-  }
-
+function clashMeta() {
+  const name = META_MAP[`${platform}-${arch}`];
   const isWin = platform === "win32";
-  const ext = isWin ? "zip" : "gz";
-  const url = `${urlPrefix}${latestVersion}/${name}-${latestVersion}.${ext}`;
-  const exefile = `${name}${isWin ? ".exe" : ""}`;
-  const zipfile = `${name}-${latestVersion}.${ext}`;
-
-  return { url, zip: ext, exefile, zipfile };
+  const urlExt = isWin ? "zip" : "gz";
+  const downloadURL = `${META_URL_PREFIX}${META_VERSION}/${name}-${META_VERSION}.${urlExt}`;
+  const exeFile = `${name}${isWin ? ".exe" : ""}`;
+  const zipFile = `${name}-${META_VERSION}.${urlExt}`;
+
+  return {
+    name: "clash-meta",
+    targetFile: `clash-meta-${SIDECAR_HOST}${isWin ? ".exe" : ""}`,
+    exeFile,
+    zipFile,
+    downloadURL,
+  };
 }
 
 /**
- * get the sidecar bin
- * clash and Clash Meta
+ * download sidecar and rename
  */
-async function resolveSidecar() {
-  const sidecarDir = path.join(cwd, "src-tauri", "sidecar");
-
-  const host = execSync("rustc -vV")
-    .toString()
-    .match(/(?<=host: ).+(?=\s*)/g)[0];
-
-  const ext = process.platform === "win32" ? ".exe" : "";
-
-  await clash();
-  if (!NO_META) await clashMeta();
+async function resolveSidecar(binInfo) {
+  const { name, targetFile, zipFile, exeFile, downloadURL } = binInfo;
 
-  async function clash() {
-    const sidecarFile = `clash-${host}${ext}`;
-    const sidecarPath = path.join(sidecarDir, sidecarFile);
-
-    await fs.mkdirp(sidecarDir);
-    if (!FORCE && (await fs.pathExists(sidecarPath))) return;
+  const sidecarDir = path.join(cwd, "src-tauri", "sidecar");
+  const sidecarPath = path.join(sidecarDir, targetFile);
 
-    // download sidecar
-    const binInfo = resolveClash();
-    const tempDir = path.join(TEMP_DIR, "clash");
-    const tempZip = path.join(tempDir, binInfo.zipfile);
-    const tempExe = path.join(tempDir, binInfo.exefile);
+  await fs.mkdirp(sidecarDir);
+  if (!FORCE && (await fs.pathExists(sidecarPath))) return;
 
-    await fs.mkdirp(tempDir);
-    if (!(await fs.pathExists(tempZip)))
-      await downloadFile(binInfo.url, tempZip);
+  const tempDir = path.join(TEMP_DIR, name);
+  const tempZip = path.join(tempDir, zipFile);
+  const tempExe = path.join(tempDir, exeFile);
 
-    if (binInfo.zip === "zip") {
-      const zip = new AdmZip(tempZip);
-      zip.getEntries().forEach((entry) => {
-        console.log("[INFO]: entry name", entry.entryName);
+  await fs.mkdirp(tempDir);
+  if (!(await fs.pathExists(tempZip))) await downloadFile(downloadURL, tempZip);
+
+  if (zipFile.endsWith(".zip")) {
+    const zip = new AdmZip(tempZip);
+    zip.getEntries().forEach((entry) => {
+      console.log(`[DEBUG]: ${name} entry name`, entry.entryName);
+    });
+    zip.extractAllTo(tempDir, true);
+    await fs.rename(tempExe, sidecarPath);
+    console.log(`[INFO]: ${name} unzip finished`);
+  } else {
+    // gz
+    const readStream = fs.createReadStream(tempZip);
+    const writeStream = fs.createWriteStream(sidecarPath);
+    readStream
+      .pipe(zlib.createGunzip())
+      .pipe(writeStream)
+      .on("finish", () => {
+        console.log(`[INFO]: ${name} gunzip finished`);
+        execSync(`chmod 755 ${sidecarPath}`);
+        console.log(`[INFO]: ${name} chmod binary finished`);
+      })
+      .on("error", (error) => {
+        console.error(`[ERROR]: ${name} gz failed`, error.message);
+        throw error;
       });
-      zip.extractAllTo(tempDir, true);
-      // save as sidecar
-      await fs.rename(tempExe, sidecarPath);
-      console.log(`[INFO]: unzip finished`);
-    } else {
-      // gz
-      const readStream = fs.createReadStream(tempZip);
-      const writeStream = fs.createWriteStream(sidecarPath);
-      readStream
-        .pipe(zlib.createGunzip())
-        .pipe(writeStream)
-        .on("finish", () => {
-          console.log(`[INFO]: gunzip finished`);
-          execSync(`chmod 755 ${sidecarPath}`);
-          console.log(`[INFO]: chmod binary finished`);
-        })
-        .on("error", (error) => console.error(error));
-    }
-
-    // delete temp dir
-    await fs.remove(tempDir);
   }
 
-  async function clashMeta() {
-    const sidecarFile = `clash-meta-${host}${ext}`;
-    const sidecarPath = path.join(sidecarDir, sidecarFile);
-
-    await fs.mkdirp(sidecarDir);
-    if (!FORCE && (await fs.pathExists(sidecarPath))) return;
-
-    // download sidecar
-    const binInfo = await resolveClashMeta();
-    const tempDir = path.join(TEMP_DIR, "clash-meta");
-    const tempZip = path.join(tempDir, binInfo.zipfile);
-    const tempExe = path.join(tempDir, binInfo.exefile);
-
-    await fs.mkdirp(tempDir);
-    if (!(await fs.pathExists(tempZip)))
-      await downloadFile(binInfo.url, tempZip);
-
-    if (binInfo.zip === "zip") {
-      const zip = new AdmZip(tempZip);
-      zip.getEntries().forEach((entry) => {
-        console.log("[INFO]: entry name", entry.entryName);
-      });
-      zip.extractAllTo(tempDir, true);
-      // save as sidecar
-      await fs.rename(tempExe, sidecarPath);
-      console.log(`[INFO]: unzip finished`);
-    } else {
-      // gz
-      const readStream = fs.createReadStream(tempZip);
-      const writeStream = fs.createWriteStream(sidecarPath);
-      readStream
-        .pipe(zlib.createGunzip())
-        .pipe(writeStream)
-        .on("finish", () => {
-          console.log(`[INFO]: gunzip finished`);
-          execSync(`chmod 755 ${sidecarPath}`);
-          console.log(`[INFO]: chmod binary finished`);
-        })
-        .on("error", (error) => console.error(error));
-    }
-
-    // delete temp dir
-    await fs.remove(tempDir);
-  }
+  // delete temp dir
+  await fs.remove(tempDir);
 }
 
 /**
@@ -225,90 +175,26 @@ async function resolveWintun() {
 }
 
 /**
- * only Windows
- * get the clash-verge-service.exe
+ * download the file to the resources dir
  */
-async function resolveService() {
-  const { platform } = process;
-
-  if (platform !== "win32") return;
+async function resolveResource(binInfo) {
+  const { file, downloadURL } = binInfo;
 
   const resDir = path.join(cwd, "src-tauri/resources");
+  const targetPath = path.join(resDir, file);
 
-  const repo =
-    "https://github.com/zzzgydi/clash-verge-service/releases/download/latest";
-
-  async function help(bin) {
-    const targetPath = path.join(resDir, bin);
-
-    if (!FORCE && (await fs.pathExists(targetPath))) return;
-
-    const url = `${repo}/${bin}`;
-    await downloadFile(url, targetPath);
-  }
-
-  await fs.mkdirp(resDir);
-  await help("clash-verge-service.exe");
-  await help("install-service.exe");
-  await help("uninstall-service.exe");
-
-  console.log(`[INFO]: resolve Service finished`);
-}
-
-/**
- * get the Country.mmdb (not required)
- */
-async function resolveMmdb() {
-  const url =
-    "https://github.com/Dreamacro/maxmind-geoip/releases/download/20221012/Country.mmdb";
-
-  const resDir = path.join(cwd, "src-tauri", "resources");
-  const resPath = path.join(resDir, "Country.mmdb");
-
-  if (!FORCE && (await fs.pathExists(resPath))) return;
-
-  await fs.mkdirp(resDir);
-  await downloadFile(url, resPath);
-}
-
-/**
- * get the geosite.dat for meta
- */
-async function resolveGeosite() {
-  const url =
-    "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat";
-
-  const resDir = path.join(cwd, "src-tauri", "resources");
-  const resPath = path.join(resDir, "geosite.dat");
-
-  if (!FORCE && (await fs.pathExists(resPath))) return;
+  if (!FORCE && (await fs.pathExists(targetPath))) return;
 
   await fs.mkdirp(resDir);
-  await downloadFile(url, resPath);
-}
-
-/**
- * get the geoip.dat for meta
- */
-async function resolveGeoIP() {
-  const url =
-    "https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat";
-
-  const resDir = path.join(cwd, "src-tauri", "resources");
-  const resPath = path.join(resDir, "geoip.dat");
+  await downloadFile(downloadURL, targetPath);
 
-  if (!FORCE && (await fs.pathExists(resPath))) return;
-
-  await fs.mkdirp(resDir);
-  await downloadFile(url, resPath);
+  console.log(`[INFO]: ${file} finished`);
 }
 
 /**
  * download file and save to `path`
  */
 async function downloadFile(url, path) {
-  console.log(`[INFO]: downloading from "${url}"`);
-
   const options = {};
 
   const httpProxy =
@@ -332,16 +218,70 @@ async function downloadFile(url, path) {
   console.log(`[INFO]: download finished "${url}"`);
 }
 
-/// main
-resolveSidecar().catch(console.error);
-resolveWintun()
-  .catch(console.error)
-  .finally(() => {
-    resolveService().catch(console.error);
+/**
+ * main
+ */
+const SERVICE_URL =
+  "https://github.com/zzzgydi/clash-verge-service/releases/download/latest";
+
+const resolveService = () =>
+  resolveResource({
+    file: "clash-verge-service.exe",
+    downloadURL: `${SERVICE_URL}/clash-verge-service.exe`,
+  });
+const resolveInstall = () =>
+  resolveResource({
+    file: "install-service.exe",
+    downloadURL: `${SERVICE_URL}/install-service.exe`,
+  });
+const resolveUninstall = () =>
+  resolveResource({
+    file: "uninstall-service.exe",
+    downloadURL: `${SERVICE_URL}/uninstall-service.exe`,
+  });
+const resolveMmdb = () =>
+  resolveResource({
+    file: "Country.mmdb",
+    downloadURL: `https://github.com/Dreamacro/maxmind-geoip/releases/download/latest/Country.mmdb`,
+  });
+const resolveGeosite = () =>
+  resolveResource({
+    file: "geosite.dat",
+    downloadURL: `https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat`,
   });
-resolveMmdb()
-  .catch(console.error)
-  .finally(() => {
-    resolveGeosite().catch(console.error);
-    // resolveGeoIP().catch(console.error);
+const resolveGeoIP = () =>
+  resolveResource({
+    file: "geoip.dat",
+    downloadURL: `https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat`,
   });
+
+const tasks = [
+  { name: "clash", func: () => resolveSidecar(clash()), retry: 5 },
+  { name: "clash-meta", func: () => resolveSidecar(clashMeta()), retry: 5 },
+  { name: "wintun", func: resolveWintun, retry: 5, winOnly: true },
+  { name: "service", func: resolveService, retry: 5, winOnly: true },
+  { name: "install", func: resolveInstall, retry: 5, winOnly: true },
+  { name: "uninstall", func: resolveUninstall, retry: 5, winOnly: true },
+  { name: "mmdb", func: resolveMmdb, retry: 5 },
+  { name: "geosite", func: resolveGeosite, retry: 5 },
+  { name: "geoip", func: resolveGeoIP, retry: 5 },
+];
+
+async function runTask() {
+  const task = tasks.shift();
+  if (!task) return;
+  if (task.winOnly && process.platform !== "win32") return;
+
+  for (let i = 0; i < task.retry; i++) {
+    try {
+      await task.func();
+      break;
+    } catch (err) {
+      console.error(`[ERROR]: task::${task.name} try ${i} == `, err.message);
+    }
+  }
+  return runTask();
+}
+
+runTask();
+runTask();
-- 
GitLab