# electron-auto-updater-enhanced

# 支持 1，增量更新（无需安装，请确保文件夹有读写权限） 2，强制更新 3，静默更新 4，版本回退（增量更新后可以回退） 5，日志输出 6，自定义灰度 目前仅支持 windows

## 安装

```bash
npm install electron-auto-updater-enhanced
yarn add electron-auto-updater-enhanced
```

#### 演示地址

```
https://github.com/huhulanglang/electron-update-add.git
```

#### 初始化

```
const ElectronAutoUpdater = require("electron-auto-updater-enhanced");

updateManager = new ElectronAutoUpdater({
    mainWindow: mainWindow, // 传递主窗口对象给更新管理器
    logPath: logPath  // 日志路径
  });
```

#### 监听日志

```
updateManager.emitter.on('auto-update-log', (data) => {
    console.log(data);
  });
```

#### 检查更新

```
updateManager.checkForUpdateVersion(url);   // url 为更新地址
```

#### 强制更新

```
updateManager.checkForUpdates();
```

#### 静默更新

```
  updateManager.updateInProgress = true;
      updateManager
        .updateDownloadFile(updateManager.silentZipPath)
        .then(() => {
        })
        .catch((err) => {
        });
```

#### 版本回退

```
updateManager.reduction(
    path.join(process.resourcesPath, "./app.asar.unpacked")
);
```

#### afterPack.js 示例 (afterPack.js 为 electron-builder 的钩子函数 afterPack)

```
const path = require('path');
const fs = require('fs');
const crypto = require('crypto');
const package = require('./package.json');
const AdmZip = require('adm-zip');
function calculateMD5(filePath) {
  return new Promise((resolve, reject) => {
    const md5 = crypto.createHash('md5');
    const stream = fs.createReadStream(filePath);
    stream.on('data', chunk => md5.update(chunk));
    stream.on('end', () => {
      const hex = md5.digest('hex');
      resolve(hex);
    });
    stream.on('error', (err) => {
      reject(err);
    });
  })
}
exports.default = async function(context) {
  let targetPath
  if(context.packager.platform.nodeName === 'darwin') {
    targetPath = path.join(context.appOutDir, `${context.packager.appInfo.productName}.app/Contents/Resources`);
  } else {
    targetPath = path.join(context.appOutDir, './resources');
  }
  const appPath = path.join(targetPath, './app.asar.unpacked');//打包文件路径
  var zip = new AdmZip();
  zip.addLocalFolder(appPath);
  const unpacked = path.join(context.outDir, 'unpacked.zip');
  zip.writeZip(unpacked);
  const md5Value = await calculateMD5(unpacked);
  const jsonData = {
    version:package.version,
    percentage:1,   //灰度
    updatePath:"",   //自定义更新地址，不填默认资源下载地址
    md5:md5Value,
    isSilent:false   //静默更新
  };
  var jsonContent = JSON.stringify(jsonData);
  fs.writeFile(path.join(context.outDir, "pcVersion.json"), jsonContent, 'utf8', function (err) {
    if (err) {
      console.log(err);
    }
 });
}

```

#### logger.js 示例

```
const {
    app,
    dialog
} = require("electron");
const log = require("electron-log");
const fs = require("fs");
const path = require("path");
const dataCu = new Date();
const year = dataCu.getFullYear();
const month = (dataCu.getMonth() + 1).toString().padStart(2, '0'); // 确保月份为两位数
const day = dataCu.getDate().toString().padStart(2, '0'); // 确保日期为两位数
const fullDateName = year + "-" + month + "-" + day + ".log";
const logDir = path.join(path.dirname(app.getPath('exe')), 'logs');
try {
    if (!fs.existsSync(logDir)) {
        fs.mkdirSync(logDir); // 如果目录不存在，则创建
    }
} catch (error) {
    const response = dialog.showMessageBoxSync({
        type: 'error',
        title: '日志目录创建失败',
        message: `无法创建日志目录: ${logDir}`,
        detail: `错误信息: ${error.message}\n请以管理员账号运行程序，选择仅为自己安装，否则可能会导致程序无法正常运行或更新。`,
        buttons: ['退出', '继续运行'],
        defaultId: 0,
        cancelId: 1
    });
    if (response === 0) {
        app.quit();
    }
    log.error("Error occurred while creating log directory:", error);
}

log.transports.console.format = "{h}:{i}:{s} {text}";
log.transports.file.maxSize = 50 * 1024 * 1024;
const logPath = path.join(logDir, fullDateName);
log.transports.file.resolvePath = () => {
    return logPath;
};
const MAX_LOG_AGE_DAYS = 30;
function cleanUpLogs() {
    try {
        const files = fs.readdirSync(logDir);

        files.forEach(file => {
            if (file.endsWith('.log')) { // 只处理.log结尾的文件
                const filePath = path.join(logDir, file);
                const stats = fs.statSync(filePath);
                const now = new Date();
                const fileAgeDays = (now - stats.mtime) / (24 * 60 * 60 * 1000);

                if (fileAgeDays > MAX_LOG_AGE_DAYS) {
                    fs.unlinkSync(filePath);
                    log.info(`Deleted expired log file: ${filePath}`);
                }
            }
        });
    } catch (err) {
        log.error("Error occurred while cleaning up logs:", err);
    }
}
module.exports = {
    log,
    logPath,
    cleanUpLogs
}
```
