github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/client/src/app/utils/hot-update.js (about) 1 import {app} from 'electron'; 2 import { 3 changeVersion, checkMd5, getAppUrl, 4 getCurrVersion, 5 getDownloadPath, 6 getRemoteVersion, 7 getResPath, mkdir, 8 restart 9 } from "./comm"; 10 import { 11 electronMsgDownloading, 12 electronMsgDownloadSuccess, 13 electronMsgUpdate, 14 electronMsgUpdateFail, 15 } from "./consts"; 16 import path from "path"; 17 import {execSync} from 'child_process'; 18 import {IS_WINDOWS_OS} from "../utils/env"; 19 import fse from 'fs-extra' 20 import {logErr, logInfo} from "./log"; 21 22 const admZip = require('adm-zip'); 23 import {promisify} from 'node:util'; 24 import stream from 'node:stream'; 25 import fs from 'node:fs'; 26 import got from 'got'; 27 import os from "os"; 28 import {killZdServer} from "../core/zd"; 29 const pipeline = promisify(stream.pipeline); 30 31 mkdir(path.join('tmp', 'download')) 32 33 export async function checkUpdate(mainWin) { 34 logInfo('checkUpdate ...') 35 36 const {currVersion, currVersionStr} = getCurrVersion() 37 38 const {newVersion, newVersionStr, forceUpdate} = await getRemoteVersion() 39 logInfo(`currVersion=${currVersion}, newVersion=${newVersion}, forceUpdate=${forceUpdate}`) 40 logInfo(currVersion < newVersion) 41 if (currVersion < newVersion) { 42 if (forceUpdate) { 43 // logInfo('forceUpdate') 44 } else { 45 mainWin.webContents.send(electronMsgUpdate, { 46 currVersionStr, newVersionStr, forceUpdate 47 }) 48 } 49 } 50 } 51 52 export const downLoadAndUpdateApp = (version, mainWin) => { 53 const downloadUrl = getAppUrl(version) 54 const downloadPath = getDownloadPath(version) 55 56 const downloadStream = got.stream(downloadUrl); 57 const fileWriterStream = fs.createWriteStream(downloadPath); 58 59 logInfo(`start download ${downloadUrl} ...`) 60 61 downloadStream.on("downloadProgress", ({ transferred, total, percent }) => { 62 mainWin.webContents.send(electronMsgDownloading, {percent}) 63 }); 64 65 pipeline(downloadStream, fileWriterStream).then(async () => { 66 logInfo(`success to downloaded to ${downloadPath}`) 67 68 const md5Pass = await checkMd5(version, downloadPath) 69 logInfo(`md5Pass ${md5Pass}`) 70 if (md5Pass) { 71 await copyFiles(downloadPath); 72 logInfo(`1 ${md5Pass}`) 73 changeVersion(version); 74 logInfo(`2 ${md5Pass}`) 75 76 mainWin.webContents.send(electronMsgDownloadSuccess, {success: true}) 77 logInfo(`3 ${md5Pass}`) 78 } else { 79 throw new Error('check md5 failed') 80 } 81 82 }).catch((err) => { 83 logErr(`upgrade app failed: ${err}`) 84 mainWin.webContents.send(electronMsgUpdateFail, {err: err.message}) 85 }); 86 } 87 88 const copyFiles = async (downloadPath) => { 89 const downloadDir = path.dirname(downloadPath) 90 91 const extractedPath = path.resolve(downloadDir, 'extracted') 92 logInfo(`downloadPath=${downloadPath}, extractedPath=${extractedPath}`) 93 94 const unzip = new admZip(downloadPath, {}); 95 let pass = '' 96 await unzip.extractAllTo(extractedPath, true, true, pass); 97 logInfo(pass) 98 99 const {uiPath, serverPath} = getResPath() 100 logInfo(`uiPath=${uiPath}, serverPath=${serverPath}`) 101 102 killZdServer(); 103 fs.rmSync(uiPath, {recursive: true}) 104 fs.rmSync(serverPath) 105 106 const serverFile = `server${os.platform() === 'win32' ? '.exe' : ''}` 107 const serverDir = path.dirname(serverPath) 108 logInfo(`serverDir=${serverDir}`) 109 const serverDist = path.join(serverDir, serverFile) 110 logInfo(`serverFile=${serverFile}, serverDist=${serverDist}`) 111 112 fse.copySync(path.resolve(downloadDir, 'extracted', 'ui'), path.resolve(path.dirname(uiPath), 'ui'), {recursive: true}) 113 fse.copySync(path.resolve(downloadDir, 'extracted', serverFile), serverDist) 114 115 if (!IS_WINDOWS_OS) { 116 const cmd = `chmod +x ${serverDist}` 117 execSync(cmd, {windowsHide: true}) 118 } 119 } 120 121 export function reboot() { 122 app.relaunch({ 123 args: process.argv.slice(1) 124 }); 125 app.exit(0); 126 }