Skip to content
js
const { join } = require("path");
const { readFile, readJSON, outputJSON, existsSync, rm } = require("fs-extra");

const getObject = require("./get-object");
const putObject = require("./put-object");
const deleteObject = require("./delete-object");

// unpacked 后续更新使用这个方法
const updateUnpacked = async () => {
  const { version } = JSON.parse(await getObject("resources/app/package.json"));
  const { version: latestVersion } = await readJSON(
    join(
      __dirname,
      "../../dist-electron/win-unpacked/resources/app/package.json"
    )
  );

  if (version === latestVersion) {
    return;
  }

  const recorderPath = join(
    __dirname,
    `./file-recorder-for-cloudflare-${latestVersion}.json`
  );

  if (existsSync(recorderPath)) {
    const fileRecords = await readJSON(recorderPath);
    const files = Object.keys(fileRecords);
    const downloadFiles = files.filter(
      (file) =>
        file !== "resources\\app\\package.json" &&
        fileRecords[file].type == "download"
    );
    // package.json 移动到最后面
    downloadFiles.push("resources\\app\\package.json");
    const rmFiles = files.filter((file) => fileRecords[file].type == "rm");
    console.log(`需要上传 ${downloadFiles.length} 个文件`);
    console.log(`需要删除 ${rmFiles.length} 个文件`);
    await onDownloadFiles(downloadFiles, fileRecords, recorderPath);
    await onRmFiles(rmFiles, fileRecords, recorderPath);
    await rm(recorderPath);
    console.log("更新完成");
    return;
  }

  const hashMap = JSON.parse(await getObject("resources/app/hash-map.json"));
  const latestHashMap = await readJSON(
    join(
      __dirname,
      "../../dist-electron/win-unpacked/resources/app/hash-map.json"
    )
  );
  const downloadFiles = [];
  const rmFiles = [];
  const fileRecords = {};

  for (const filepath in latestHashMap) {
    const { hash } = hashMap[filepath] || {};
    const { hash: latestHash } = latestHashMap[filepath];

    if (!hash) {
      // 新增的文件
      downloadFiles.push(filepath);
      fileRecords[filepath] = { type: "download" };
    } else if (hash !== latestHash) {
      // 内容改变的文件
      if (filepath !== "resources\\app\\package.json") {
        // package.json 一定要是最后一个下载的文件,因为版本号决定了是否更新
        downloadFiles.push(filepath);
        fileRecords[filepath] = { type: "download" };
      }
    }
  }

  // 不要忘记更新 hash-map.json
  const hashMapFilepath = "resources\\app\\hash-map.json";
  downloadFiles.push(hashMapFilepath);
  fileRecords[hashMapFilepath] = { type: "download" };
  downloadFiles.push("resources\\app\\package.json");
  fileRecords["resources\\app\\package.json"] = { type: "download" };

  for (const filepath in hashMap) {
    if (!latestHashMap[filepath]) {
      // 需要删除的文件
      rmFiles.push(filepath);
      fileRecords[filepath] = { type: "rm" };
    }
  }

  console.log(`需要上传 ${downloadFiles.length} 个文件`);
  console.log(`需要删除 ${rmFiles.length} 个文件`);

  await outputJSON(recorderPath, fileRecords, { spaces: 2 });
  await onDownloadFiles(downloadFiles, fileRecords, recorderPath);
  await onRmFiles(rmFiles, fileRecords, recorderPath);
  await rm(recorderPath);
  console.log("Cloudflare 更新完成");
};

const onDownloadFiles = async (downloadFiles, fileRecords, recorderPath) => {
  for (let i = 0, l = downloadFiles.length; i < l; i++) {
    const target = downloadFiles[i];
    const localTarget = join(
      __dirname,
      "../../dist-electron/win-unpacked",
      target
    );
    const stream = await readFile(localTarget);
    const key = target.replace(/\\/g, "/");
    await putObject(localTarget, "sharp-unpacked", stream, key);
    delete fileRecords[target];
    await outputJSON(recorderPath, fileRecords, { spaces: 2 });
  }
};

const onRmFiles = async (rmFiles, fileRecords, recorderPath) => {
  for (let i = 0, l = rmFiles.length; i < l; i++) {
    const target = rmFiles[i];
    const key = target.replace(/\\/g, "/");
    await deleteObject(key);
    delete fileRecords[target];
    await outputJSON(recorderPath, fileRecords, { spaces: 2 });
  }
};

updateUnpacked();