electron-updator 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -7
- package/build/app-updator.js +246 -0
- package/build/common/constants.js +96 -0
- package/build/elelctron-app-adapter.js +33 -0
- package/build/index.js +10 -0
- package/build/libs/installer.exe +0 -0
- package/build/libs/unzip.exe +0 -0
- package/build/mac-updator.js +108 -0
- package/build/utils/download-file.js +74 -0
- package/build/utils/index.js +122 -0
- package/build/utils/install-macos-dmg.js +151 -0
- package/build/utils/sudo-prompt-exec.js +23 -0
- package/build/windows-updator.js +87 -0
- package/package.json +51 -20
- package/bin/electron-updator.js +0 -3
- package/index.js +0 -3
- package/lib/electron-updator.js +0 -1
    
        package/README.md
    CHANGED
    
    | @@ -8,23 +8,34 @@ | |
| 8 8 |  | 
| 9 9 | 
             
            [npm-image]: https://img.shields.io/npm/v/electron-updator.svg
         | 
| 10 10 | 
             
            [npm-url]: https://npmjs.org/package/electron-updator
         | 
| 11 | 
            -
            [ci-image]: https://github.com/ | 
| 12 | 
            -
            [ci-url]: https://github.com/ | 
| 13 | 
            -
            [codecov-image]: https://img.shields.io/codecov/c/github/ | 
| 14 | 
            -
            [codecov-url]: https://codecov.io/gh/ | 
| 11 | 
            +
            [ci-image]: https://github.com/electron-modules/electron-updator/actions/workflows/ci.yml/badge.svg
         | 
| 12 | 
            +
            [ci-url]: https://github.com/electron-modules/electron-updator/actions/workflows/ci.yml
         | 
| 13 | 
            +
            [codecov-image]: https://img.shields.io/codecov/c/github/electron-modules/electron-updator.svg?logo=codecov
         | 
| 14 | 
            +
            [codecov-url]: https://codecov.io/gh/electron-modules/electron-updator
         | 
| 15 15 | 
             
            [node-image]: https://img.shields.io/badge/node.js-%3E=_16-green.svg
         | 
| 16 16 | 
             
            [node-url]: http://nodejs.org/download/
         | 
| 17 17 | 
             
            [download-image]: https://img.shields.io/npm/dm/electron-updator.svg
         | 
| 18 18 | 
             
            [download-url]: https://npmjs.org/package/electron-updator
         | 
| 19 19 |  | 
| 20 | 
            -
            > electron | 
| 21 | 
            -
             | 
| 20 | 
            +
            > electron updator
         | 
| 22 21 | 
             
            ## Installment
         | 
| 23 22 |  | 
| 24 23 | 
             
            ```bash
         | 
| 25 | 
            -
            $ npm i electron-updator --save | 
| 24 | 
            +
            $ npm i electron-updator --save
         | 
| 26 25 | 
             
            ```
         | 
| 27 26 |  | 
| 27 | 
            +
            <!-- GITCONTRIBUTOR_START -->
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            ## Contributors
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            |[<img src="https://avatars.githubusercontent.com/u/1011681?v=4" width="100px;"/><br/><sub><b>xudafeng</b></sub>](https://github.com/xudafeng)<br/>|[<img src="https://avatars.githubusercontent.com/u/4081746?v=4" width="100px;"/><br/><sub><b>zlyi</b></sub>](https://github.com/zlyi)<br/>|
         | 
| 32 | 
            +
            | :---: | :---: |
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 | 
            +
            This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon Jan 30 2023 19:21:07 GMT+0800`.
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            <!-- GITCONTRIBUTOR_END -->
         | 
| 38 | 
            +
             | 
| 28 39 | 
             
            ## License
         | 
| 29 40 |  | 
| 30 41 | 
             
            The MIT License (MIT)
         | 
| @@ -0,0 +1,246 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 3 | 
            +
            exports.AppUpdator = void 0;
         | 
| 4 | 
            +
            const eventemitter3_1 = require("eventemitter3");
         | 
| 5 | 
            +
            const constants_1 = require("./common/constants");
         | 
| 6 | 
            +
            const download_file_1 = require("./utils/download-file");
         | 
| 7 | 
            +
            const utils_1 = require("./utils");
         | 
| 8 | 
            +
            const elelctron_app_adapter_1 = require("./elelctron-app-adapter");
         | 
| 9 | 
            +
            class AppUpdator extends eventemitter3_1.EventEmitter {
         | 
| 10 | 
            +
                constructor(options, app) {
         | 
| 11 | 
            +
                    super();
         | 
| 12 | 
            +
                    this.state = "idle" /* StateType.Idle */;
         | 
| 13 | 
            +
                    this.options = options;
         | 
| 14 | 
            +
                    this.logger = this._wrapLogger(options.logger);
         | 
| 15 | 
            +
                    this.app = app || new elelctron_app_adapter_1.ElectronAppAdapter();
         | 
| 16 | 
            +
                    this.startTimeStamp = new Date().getTime();
         | 
| 17 | 
            +
                    this.logger.info('AppUpdator#constructor');
         | 
| 18 | 
            +
                    this.availableUpdate = {
         | 
| 19 | 
            +
                        resourcePath: '',
         | 
| 20 | 
            +
                        latestAsarPath: '',
         | 
| 21 | 
            +
                        downloadTargetDir: '',
         | 
| 22 | 
            +
                    };
         | 
| 23 | 
            +
                }
         | 
| 24 | 
            +
                _wrapLogger(logger) {
         | 
| 25 | 
            +
                    if (!logger) {
         | 
| 26 | 
            +
                        logger = console;
         | 
| 27 | 
            +
                    }
         | 
| 28 | 
            +
                    const _logger = { ...logger };
         | 
| 29 | 
            +
                    const _wrap = (message, callback) => {
         | 
| 30 | 
            +
                        callback(`ElectronUpdator(${this.startTimeStamp})${message}`);
         | 
| 31 | 
            +
                    };
         | 
| 32 | 
            +
                    _logger.error = (message) => {
         | 
| 33 | 
            +
                        _wrap(message, logger.error);
         | 
| 34 | 
            +
                    };
         | 
| 35 | 
            +
                    _logger.info = (message) => {
         | 
| 36 | 
            +
                        _wrap(message, logger.info);
         | 
| 37 | 
            +
                    };
         | 
| 38 | 
            +
                    _logger.warn = (message) => {
         | 
| 39 | 
            +
                        _wrap(message, logger.warn);
         | 
| 40 | 
            +
                    };
         | 
| 41 | 
            +
                    return _logger;
         | 
| 42 | 
            +
                }
         | 
| 43 | 
            +
                setState(state) {
         | 
| 44 | 
            +
                    this.logger.info(`AppUpdator#setState${state}`);
         | 
| 45 | 
            +
                    this.state = state;
         | 
| 46 | 
            +
                }
         | 
| 47 | 
            +
                setFeedUrl(url) {
         | 
| 48 | 
            +
                    this.logger.info(`AppUpdator#setFeedUrl:url is ${url}`);
         | 
| 49 | 
            +
                    if (url && this.options) {
         | 
| 50 | 
            +
                        this.options.url = url;
         | 
| 51 | 
            +
                    }
         | 
| 52 | 
            +
                }
         | 
| 53 | 
            +
                async checkForUpdates(executeType = constants_1.ExecuteType.Auto) {
         | 
| 54 | 
            +
                    this.logger.info(`AppUpdator#checkForUpdates:state is ${this.state}`);
         | 
| 55 | 
            +
                    if (executeType === constants_1.ExecuteType.User) {
         | 
| 56 | 
            +
                        if (this.state === "downloaded" /* StateType.Downloaded */) {
         | 
| 57 | 
            +
                            this.logger.info(`AppUpdator#checkForUpdates:UPDATE_DOWNLOADED`);
         | 
| 58 | 
            +
                            this.emit(constants_1.EventType.UPDATE_DOWNLOADED, {
         | 
| 59 | 
            +
                                executeType,
         | 
| 60 | 
            +
                            });
         | 
| 61 | 
            +
                        }
         | 
| 62 | 
            +
                        else {
         | 
| 63 | 
            +
                            this.logger.info(`AppUpdator#checkForUpdates:UPDATE_NOT_AVAILABLE`);
         | 
| 64 | 
            +
                            this.emit(constants_1.EventType.UPDATE_NOT_AVAILABLE, { updateInfo: this.updateInfo });
         | 
| 65 | 
            +
                        }
         | 
| 66 | 
            +
                        return;
         | 
| 67 | 
            +
                    }
         | 
| 68 | 
            +
                    this.setState("idle" /* StateType.Idle */);
         | 
| 69 | 
            +
                    try {
         | 
| 70 | 
            +
                        // 新一轮更新流程,更新 TimeStamp
         | 
| 71 | 
            +
                        this.startTimeStamp = new Date().getTime();
         | 
| 72 | 
            +
                        this.setState("checking-for-update" /* StateType.CheckingForUpdate */);
         | 
| 73 | 
            +
                        this.emit(constants_1.EventType.CHECKING_FOR_UPDATE);
         | 
| 74 | 
            +
                        const updateInfoResponse = await (0, utils_1.requestUpdateInfo)(this.options);
         | 
| 75 | 
            +
                        this.updateInfo = (this.options?.responseFormatter ? this.options?.responseFormatter(updateInfoResponse) : updateInfoResponse);
         | 
| 76 | 
            +
                        const needUpdate = this.options?.needUpdate(updateInfoResponse);
         | 
| 77 | 
            +
                        if (!needUpdate) {
         | 
| 78 | 
            +
                            this.logger.info(`updateInfo is ${JSON.stringify(this.updateInfo)},needUpdate is false`);
         | 
| 79 | 
            +
                            this.emit(constants_1.EventType.UPDATE_NOT_AVAILABLE, { updateInfo: this.updateInfo });
         | 
| 80 | 
            +
                            this.setState("idle" /* StateType.Idle */);
         | 
| 81 | 
            +
                            return;
         | 
| 82 | 
            +
                        }
         | 
| 83 | 
            +
                        this.logger.info(`AppUpdator#checkForUpdates:needUpdate is true`);
         | 
| 84 | 
            +
                        this.availableUpdate = this.doGetAvailableUpdateInfo(this.updateInfo);
         | 
| 85 | 
            +
                        if (!this.options?.autoDownload) {
         | 
| 86 | 
            +
                            this.logger.info(`AppUpdator#checkForUpdates:emit UPDATE_AVAILABLE`);
         | 
| 87 | 
            +
                            this.emit(constants_1.EventType.UPDATE_AVAILABLE, {
         | 
| 88 | 
            +
                                executeType,
         | 
| 89 | 
            +
                                updateInfo: this.updateInfo,
         | 
| 90 | 
            +
                            });
         | 
| 91 | 
            +
                            return;
         | 
| 92 | 
            +
                        }
         | 
| 93 | 
            +
                        this.downloadUpdate(executeType);
         | 
| 94 | 
            +
                    }
         | 
| 95 | 
            +
                    catch (e) {
         | 
| 96 | 
            +
                        e.customMessage = e.customMessage ? e.customMessage : `${constants_1.InstallResultType.CheckForUpdatesError}_${e.message}`;
         | 
| 97 | 
            +
                        this.logError(e);
         | 
| 98 | 
            +
                        this.setState("idle" /* StateType.Idle */);
         | 
| 99 | 
            +
                    }
         | 
| 100 | 
            +
                }
         | 
| 101 | 
            +
                async downloadUpdate(executeType = constants_1.ExecuteType.User) {
         | 
| 102 | 
            +
                    this.logger.info(`AppUpdator#downloadUpdate:executeType is ${executeType}`);
         | 
| 103 | 
            +
                    await this.downloadUpdateFile(this.updateInfo);
         | 
| 104 | 
            +
                    const result = await this.preCheck();
         | 
| 105 | 
            +
                    if (result.success) {
         | 
| 106 | 
            +
                        this.logger.info(`AppUpdator#downloadUpdate:emit UPDATE_DOWNLOADED`);
         | 
| 107 | 
            +
                        this.emit(constants_1.EventType.UPDATE_DOWNLOADED, {
         | 
| 108 | 
            +
                            executeType,
         | 
| 109 | 
            +
                        });
         | 
| 110 | 
            +
                    }
         | 
| 111 | 
            +
                    else {
         | 
| 112 | 
            +
                        this.logError(result.error);
         | 
| 113 | 
            +
                        this.setState("idle" /* StateType.Idle */);
         | 
| 114 | 
            +
                    }
         | 
| 115 | 
            +
                }
         | 
| 116 | 
            +
                async quitAndInstall() {
         | 
| 117 | 
            +
                    this.logger.info(`AppUpdator#quitAndInstall:state is ${this.state}`);
         | 
| 118 | 
            +
                    if (this.state !== "downloaded" /* StateType.Downloaded */) {
         | 
| 119 | 
            +
                        return;
         | 
| 120 | 
            +
                    }
         | 
| 121 | 
            +
                    this.setState("idle" /* StateType.Idle */);
         | 
| 122 | 
            +
                    try {
         | 
| 123 | 
            +
                        let result = { success: false };
         | 
| 124 | 
            +
                        if (this.updateInfo?.updateType === constants_1.UpdateType.Package) {
         | 
| 125 | 
            +
                            result = await this.doQuitAndInstallPackage();
         | 
| 126 | 
            +
                        }
         | 
| 127 | 
            +
                        else {
         | 
| 128 | 
            +
                            result = await this.doQuitAndInstallAsar();
         | 
| 129 | 
            +
                        }
         | 
| 130 | 
            +
                        if (result.success) {
         | 
| 131 | 
            +
                            this.logger.warn(`AppUpdator#quitAndInstall:install success`);
         | 
| 132 | 
            +
                            this.emit(constants_1.EventType.BEFORE_QUIT_FOR_UPDATE);
         | 
| 133 | 
            +
                        }
         | 
| 134 | 
            +
                        else {
         | 
| 135 | 
            +
                            result.message = `error: ${result.error?.message}`;
         | 
| 136 | 
            +
                            this.dispatchError(result.error);
         | 
| 137 | 
            +
                        }
         | 
| 138 | 
            +
                    }
         | 
| 139 | 
            +
                    catch (e) {
         | 
| 140 | 
            +
                        this.dispatchError(e);
         | 
| 141 | 
            +
                    }
         | 
| 142 | 
            +
                }
         | 
| 143 | 
            +
                async preCheckForAsar() {
         | 
| 144 | 
            +
                    this.logger.info(`AppUpdator#preCheckForAsar`);
         | 
| 145 | 
            +
                    return await this.unzip();
         | 
| 146 | 
            +
                }
         | 
| 147 | 
            +
                async preCheck() {
         | 
| 148 | 
            +
                    this.logger.info(`AppUpdator#preCheck`);
         | 
| 149 | 
            +
                    const { resourcePath } = this.availableUpdate;
         | 
| 150 | 
            +
                    if (this.state !== "downloaded" /* StateType.Downloaded */) {
         | 
| 151 | 
            +
                        return {
         | 
| 152 | 
            +
                            success: false,
         | 
| 153 | 
            +
                            error: new Error(`AppUpdator#preCheck:update status(${this.state}) error`),
         | 
| 154 | 
            +
                        };
         | 
| 155 | 
            +
                    }
         | 
| 156 | 
            +
                    // 清理老包
         | 
| 157 | 
            +
                    try {
         | 
| 158 | 
            +
                        this.logger.info(`AppUpdator#preCheck:cleanOldArchive`);
         | 
| 159 | 
            +
                        await (0, utils_1.cleanOldArchive)(resourcePath);
         | 
| 160 | 
            +
                    }
         | 
| 161 | 
            +
                    catch (e) {
         | 
| 162 | 
            +
                        this.logError(e);
         | 
| 163 | 
            +
                    }
         | 
| 164 | 
            +
                    let result = { success: true };
         | 
| 165 | 
            +
                    const { downloadTargetDir } = this.availableUpdate;
         | 
| 166 | 
            +
                    try {
         | 
| 167 | 
            +
                        const hasLatestFile = await (0, utils_1.existsAsync)(downloadTargetDir);
         | 
| 168 | 
            +
                        // 下载失败返回提示
         | 
| 169 | 
            +
                        if (!hasLatestFile) {
         | 
| 170 | 
            +
                            return {
         | 
| 171 | 
            +
                                success: false,
         | 
| 172 | 
            +
                                error: new Error('file is notfound'),
         | 
| 173 | 
            +
                            };
         | 
| 174 | 
            +
                        }
         | 
| 175 | 
            +
                    }
         | 
| 176 | 
            +
                    catch (e) {
         | 
| 177 | 
            +
                        return {
         | 
| 178 | 
            +
                            success: false,
         | 
| 179 | 
            +
                            error: e,
         | 
| 180 | 
            +
                        };
         | 
| 181 | 
            +
                    }
         | 
| 182 | 
            +
                    if (this.updateInfo?.updateType === constants_1.UpdateType.Package) {
         | 
| 183 | 
            +
                        result = await this.doPreCheckForPackage();
         | 
| 184 | 
            +
                    }
         | 
| 185 | 
            +
                    else {
         | 
| 186 | 
            +
                        result = await this.preCheckForAsar();
         | 
| 187 | 
            +
                    }
         | 
| 188 | 
            +
                    return result;
         | 
| 189 | 
            +
                }
         | 
| 190 | 
            +
                async downloadUpdateFile(updateInfo) {
         | 
| 191 | 
            +
                    if (this.state !== "checking-for-update" /* StateType.CheckingForUpdate */) {
         | 
| 192 | 
            +
                        throw new Error(`AppUpdator#downloadUpdateFile:update status(${this.state}) error`);
         | 
| 193 | 
            +
                    }
         | 
| 194 | 
            +
                    const { url, signature } = updateInfo.files[0];
         | 
| 195 | 
            +
                    const { downloadTargetDir } = this.availableUpdate;
         | 
| 196 | 
            +
                    this.setState("downloading" /* StateType.Downloading */);
         | 
| 197 | 
            +
                    try {
         | 
| 198 | 
            +
                        await (0, download_file_1.downloadFile)({
         | 
| 199 | 
            +
                            logger: this.logger,
         | 
| 200 | 
            +
                            url,
         | 
| 201 | 
            +
                            signature,
         | 
| 202 | 
            +
                            targetDir: downloadTargetDir,
         | 
| 203 | 
            +
                            emit: this.emit,
         | 
| 204 | 
            +
                            progressHandle: (data) => {
         | 
| 205 | 
            +
                                this.emit(constants_1.EventType.UPDATE_DOWNLOAD_PROGRESS, data);
         | 
| 206 | 
            +
                            },
         | 
| 207 | 
            +
                        });
         | 
| 208 | 
            +
                        this.logger.info(`AppUpdator#downloadUpdateFile:Downloaded`);
         | 
| 209 | 
            +
                        this.setState("downloaded" /* StateType.Downloaded */);
         | 
| 210 | 
            +
                    }
         | 
| 211 | 
            +
                    catch (e) {
         | 
| 212 | 
            +
                        this.setState("idle" /* StateType.Idle */);
         | 
| 213 | 
            +
                        e.customMessage = `${constants_1.InstallResultType.DownloadError}_${e.message}`;
         | 
| 214 | 
            +
                        this.logError(e);
         | 
| 215 | 
            +
                    }
         | 
| 216 | 
            +
                }
         | 
| 217 | 
            +
                async unzip() {
         | 
| 218 | 
            +
                    this.logger.info(`AppUpdator#unzip:start`);
         | 
| 219 | 
            +
                    try {
         | 
| 220 | 
            +
                        const result = await this.doUnzip();
         | 
| 221 | 
            +
                        if (!result.success) {
         | 
| 222 | 
            +
                            return result;
         | 
| 223 | 
            +
                        }
         | 
| 224 | 
            +
                        const { latestAsarPath } = this.availableUpdate;
         | 
| 225 | 
            +
                        const exist = await (0, utils_1.existFile)(latestAsarPath);
         | 
| 226 | 
            +
                        return Promise.resolve({ success: exist });
         | 
| 227 | 
            +
                    }
         | 
| 228 | 
            +
                    catch (error) {
         | 
| 229 | 
            +
                        error.customMessage = constants_1.InstallResultType.UpdateUnzipError;
         | 
| 230 | 
            +
                        return Promise.resolve({
         | 
| 231 | 
            +
                            success: false,
         | 
| 232 | 
            +
                            error,
         | 
| 233 | 
            +
                        });
         | 
| 234 | 
            +
                    }
         | 
| 235 | 
            +
                }
         | 
| 236 | 
            +
                dispatchError(e) {
         | 
| 237 | 
            +
                    this.logError(e);
         | 
| 238 | 
            +
                    this.emit(constants_1.EventType.ERROR, e.message);
         | 
| 239 | 
            +
                }
         | 
| 240 | 
            +
                logError(e) {
         | 
| 241 | 
            +
                    const message = (e.stack || e).toString();
         | 
| 242 | 
            +
                    this.logger.error(message);
         | 
| 243 | 
            +
                }
         | 
| 244 | 
            +
            }
         | 
| 245 | 
            +
            exports.AppUpdator = AppUpdator;
         | 
| 246 | 
            +
            //# sourceMappingURL=app-updator.js.map
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 3 | 
            +
            exports.EventType = exports.DownloadProgressStatus = exports.ExecuteType = exports.UpdateType = exports.InstallResultType = exports.OldArchivePrefix = void 0;
         | 
| 4 | 
            +
            /**
         | 
| 5 | 
            +
             * 更新包备份前缀
         | 
| 6 | 
            +
             */
         | 
| 7 | 
            +
            exports.OldArchivePrefix = 'old-';
         | 
| 8 | 
            +
            /**
         | 
| 9 | 
            +
             * 安装结果类型
         | 
| 10 | 
            +
             */
         | 
| 11 | 
            +
            var InstallResultType;
         | 
| 12 | 
            +
            (function (InstallResultType) {
         | 
| 13 | 
            +
                InstallResultType["UpdateUnzipError"] = "update-unzip-error";
         | 
| 14 | 
            +
                InstallResultType["DownloadError"] = "download-error";
         | 
| 15 | 
            +
                InstallResultType["UpdateSuccess"] = "update-success";
         | 
| 16 | 
            +
                InstallResultType["CheckForUpdatesError"] = "check-for-updates-error";
         | 
| 17 | 
            +
            })(InstallResultType = exports.InstallResultType || (exports.InstallResultType = {}));
         | 
| 18 | 
            +
            /**
         | 
| 19 | 
            +
             * 更新类型
         | 
| 20 | 
            +
             */
         | 
| 21 | 
            +
            var UpdateType;
         | 
| 22 | 
            +
            (function (UpdateType) {
         | 
| 23 | 
            +
                /** 全量更新 */
         | 
| 24 | 
            +
                UpdateType["Package"] = "package";
         | 
| 25 | 
            +
                /** 动态更新 */
         | 
| 26 | 
            +
                UpdateType["Asar"] = "asar";
         | 
| 27 | 
            +
                /** 更新包更新 */
         | 
| 28 | 
            +
                UpdateType["Assets"] = "assets";
         | 
| 29 | 
            +
            })(UpdateType = exports.UpdateType || (exports.UpdateType = {}));
         | 
| 30 | 
            +
            /**
         | 
| 31 | 
            +
             * 执行类型
         | 
| 32 | 
            +
             */
         | 
| 33 | 
            +
            var ExecuteType;
         | 
| 34 | 
            +
            (function (ExecuteType) {
         | 
| 35 | 
            +
                /**
         | 
| 36 | 
            +
                 * 自动触发
         | 
| 37 | 
            +
                 */
         | 
| 38 | 
            +
                ExecuteType["User"] = "user";
         | 
| 39 | 
            +
                /**
         | 
| 40 | 
            +
                 * 手动触发
         | 
| 41 | 
            +
                 */
         | 
| 42 | 
            +
                ExecuteType["Auto"] = "auto";
         | 
| 43 | 
            +
            })(ExecuteType = exports.ExecuteType || (exports.ExecuteType = {}));
         | 
| 44 | 
            +
            /**
         | 
| 45 | 
            +
             * 执行类型
         | 
| 46 | 
            +
             */
         | 
| 47 | 
            +
            var DownloadProgressStatus;
         | 
| 48 | 
            +
            (function (DownloadProgressStatus) {
         | 
| 49 | 
            +
                /**
         | 
| 50 | 
            +
                 * 开始
         | 
| 51 | 
            +
                 */
         | 
| 52 | 
            +
                DownloadProgressStatus["Begin"] = "begin";
         | 
| 53 | 
            +
                /**
         | 
| 54 | 
            +
                 * 下载中
         | 
| 55 | 
            +
                 */
         | 
| 56 | 
            +
                DownloadProgressStatus["Downloading"] = "downloading";
         | 
| 57 | 
            +
                /**
         | 
| 58 | 
            +
                 * 结束
         | 
| 59 | 
            +
                 */
         | 
| 60 | 
            +
                DownloadProgressStatus["End"] = "end";
         | 
| 61 | 
            +
            })(DownloadProgressStatus = exports.DownloadProgressStatus || (exports.DownloadProgressStatus = {}));
         | 
| 62 | 
            +
            /**
         | 
| 63 | 
            +
             * 事件类型
         | 
| 64 | 
            +
             */
         | 
| 65 | 
            +
            var EventType;
         | 
| 66 | 
            +
            (function (EventType) {
         | 
| 67 | 
            +
                /**
         | 
| 68 | 
            +
                 * 下载完成
         | 
| 69 | 
            +
                 */
         | 
| 70 | 
            +
                EventType["UPDATE_DOWNLOADED"] = "update-downloaded";
         | 
| 71 | 
            +
                /**
         | 
| 72 | 
            +
                 * 下载进度
         | 
| 73 | 
            +
                 */
         | 
| 74 | 
            +
                EventType["UPDATE_DOWNLOAD_PROGRESS"] = "update-download-progress";
         | 
| 75 | 
            +
                /**
         | 
| 76 | 
            +
                 * 用户调用 quitAndInstall 之后发出,可在次事件后完成关闭窗口、重启等操作
         | 
| 77 | 
            +
                 */
         | 
| 78 | 
            +
                EventType["BEFORE_QUIT_FOR_UPDATE"] = "before-quit-for-update";
         | 
| 79 | 
            +
                /**
         | 
| 80 | 
            +
                 * 有可用更新
         | 
| 81 | 
            +
                 */
         | 
| 82 | 
            +
                EventType["UPDATE_AVAILABLE"] = "update-available";
         | 
| 83 | 
            +
                /**
         | 
| 84 | 
            +
                 * 开始检查更新
         | 
| 85 | 
            +
                 */
         | 
| 86 | 
            +
                EventType["CHECKING_FOR_UPDATE"] = "checking-for-update";
         | 
| 87 | 
            +
                /**
         | 
| 88 | 
            +
                 * 无可用更新
         | 
| 89 | 
            +
                 */
         | 
| 90 | 
            +
                EventType["UPDATE_NOT_AVAILABLE"] = "update-not-available";
         | 
| 91 | 
            +
                /**
         | 
| 92 | 
            +
                 * 错误
         | 
| 93 | 
            +
                 */
         | 
| 94 | 
            +
                EventType["ERROR"] = "error";
         | 
| 95 | 
            +
            })(EventType = exports.EventType || (exports.EventType = {}));
         | 
| 96 | 
            +
            //# sourceMappingURL=constants.js.map
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 3 | 
            +
            exports.ElectronAppAdapter = void 0;
         | 
| 4 | 
            +
            const electron_1 = require("electron");
         | 
| 5 | 
            +
            class ElectronAppAdapter {
         | 
| 6 | 
            +
                constructor(app = electron_1.app) {
         | 
| 7 | 
            +
                    this.app = app;
         | 
| 8 | 
            +
                }
         | 
| 9 | 
            +
                get name() {
         | 
| 10 | 
            +
                    return this.app.getName();
         | 
| 11 | 
            +
                }
         | 
| 12 | 
            +
                get isPackaged() {
         | 
| 13 | 
            +
                    return this.app.isPackaged === true;
         | 
| 14 | 
            +
                }
         | 
| 15 | 
            +
                get userDataPath() {
         | 
| 16 | 
            +
                    return this.app.getPath('userData');
         | 
| 17 | 
            +
                }
         | 
| 18 | 
            +
                get exePath() {
         | 
| 19 | 
            +
                    return this.app.getPath('exe');
         | 
| 20 | 
            +
                }
         | 
| 21 | 
            +
                exit(code) {
         | 
| 22 | 
            +
                    this.app.exit(code);
         | 
| 23 | 
            +
                }
         | 
| 24 | 
            +
                relaunch(code) {
         | 
| 25 | 
            +
                    this.app.relaunch();
         | 
| 26 | 
            +
                    this.app.exit(code);
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
                quit() {
         | 
| 29 | 
            +
                    this.app.quit();
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
            }
         | 
| 32 | 
            +
            exports.ElectronAppAdapter = ElectronAppAdapter;
         | 
| 33 | 
            +
            //# sourceMappingURL=elelctron-app-adapter.js.map
         | 
    
        package/build/index.js
    ADDED
    
    | @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 3 | 
            +
            const constants_1 = require("./common/constants");
         | 
| 4 | 
            +
            const mac_updator_1 = require("./mac-updator");
         | 
| 5 | 
            +
            const windows_updator_1 = require("./windows-updator");
         | 
| 6 | 
            +
            exports.default = {
         | 
| 7 | 
            +
                UpdateType: constants_1.UpdateType, EventType: constants_1.EventType, ExecuteType: constants_1.ExecuteType,
         | 
| 8 | 
            +
                MacUpdator: mac_updator_1.MacUpdator, WindowsUpdator: windows_updator_1.WindowsUpdator, DownloadProgressStatus: constants_1.DownloadProgressStatus,
         | 
| 9 | 
            +
            };
         | 
| 10 | 
            +
            //# sourceMappingURL=index.js.map
         | 
| Binary file | 
| Binary file | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            var __importDefault = (this && this.__importDefault) || function (mod) {
         | 
| 3 | 
            +
                return (mod && mod.__esModule) ? mod : { "default": mod };
         | 
| 4 | 
            +
            };
         | 
| 5 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 6 | 
            +
            exports.MacUpdator = void 0;
         | 
| 7 | 
            +
            const path_1 = __importDefault(require("path"));
         | 
| 8 | 
            +
            const app_updator_1 = require("./app-updator");
         | 
| 9 | 
            +
            const constants_1 = require("./common/constants");
         | 
| 10 | 
            +
            const install_macos_dmg_1 = __importDefault(require("./utils/install-macos-dmg"));
         | 
| 11 | 
            +
            const utils_1 = require("./utils");
         | 
| 12 | 
            +
            class MacUpdator extends app_updator_1.AppUpdator {
         | 
| 13 | 
            +
                constructor(options) {
         | 
| 14 | 
            +
                    super(options);
         | 
| 15 | 
            +
                }
         | 
| 16 | 
            +
                doGetAvailableUpdateInfo(updateInfo) {
         | 
| 17 | 
            +
                    this.logger.info('MacUpdator#doGetAvailableUpdateInfo:start');
         | 
| 18 | 
            +
                    const exePath = this.app.exePath;
         | 
| 19 | 
            +
                    const resourcePath = path_1.default.resolve(exePath, '..', '..', 'Resources');
         | 
| 20 | 
            +
                    const latestAsarPath = path_1.default.resolve(resourcePath, 'latest.asar');
         | 
| 21 | 
            +
                    const latestAppPath = path_1.default.resolve(resourcePath, 'latest');
         | 
| 22 | 
            +
                    let downloadTargetDir = `${latestAsarPath}.zip`;
         | 
| 23 | 
            +
                    if (updateInfo.updateType === constants_1.UpdateType.Package) {
         | 
| 24 | 
            +
                        downloadTargetDir = `${latestAppPath}.dmg`;
         | 
| 25 | 
            +
                    }
         | 
| 26 | 
            +
                    return {
         | 
| 27 | 
            +
                        resourcePath,
         | 
| 28 | 
            +
                        downloadTargetDir,
         | 
| 29 | 
            +
                        latestAsarPath,
         | 
| 30 | 
            +
                    };
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
                async doPreCheckForPackage() {
         | 
| 33 | 
            +
                    this.logger.info('MacUpdator#doPreCheckForPackage:start');
         | 
| 34 | 
            +
                    // Mac 全量安装前,先进行 dmg 安装检查
         | 
| 35 | 
            +
                    return await (0, install_macos_dmg_1.default)(this.options, this.logger, this.availableUpdate, this.updateInfo, true);
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
                /**
         | 
| 38 | 
            +
                 * 资源解压
         | 
| 39 | 
            +
                 * @return
         | 
| 40 | 
            +
                 */
         | 
| 41 | 
            +
                async doUnzip() {
         | 
| 42 | 
            +
                    this.logger.info('MacUpdator#doUnzip:start');
         | 
| 43 | 
            +
                    const { resourcePath, downloadTargetDir } = this.availableUpdate;
         | 
| 44 | 
            +
                    try {
         | 
| 45 | 
            +
                        // 直接解压
         | 
| 46 | 
            +
                        await (0, utils_1.execAsync)(`unzip -o ${downloadTargetDir}`, {
         | 
| 47 | 
            +
                            cwd: resourcePath,
         | 
| 48 | 
            +
                            maxBuffer: 2 ** 28,
         | 
| 49 | 
            +
                        });
         | 
| 50 | 
            +
                        return {
         | 
| 51 | 
            +
                            success: true,
         | 
| 52 | 
            +
                        };
         | 
| 53 | 
            +
                    }
         | 
| 54 | 
            +
                    catch (error) {
         | 
| 55 | 
            +
                        return {
         | 
| 56 | 
            +
                            success: false,
         | 
| 57 | 
            +
                            error,
         | 
| 58 | 
            +
                        };
         | 
| 59 | 
            +
                    }
         | 
| 60 | 
            +
                }
         | 
| 61 | 
            +
                async doQuitAndInstallAsar() {
         | 
| 62 | 
            +
                    this.logger.info('MacUpdator#doQuitAndInstallAsar:start');
         | 
| 63 | 
            +
                    if (!this.availableUpdate) {
         | 
| 64 | 
            +
                        this.logger.error('MacUpdator#doQuitAndInstallAsar:not availableUpdate');
         | 
| 65 | 
            +
                        return Promise.resolve({ success: false });
         | 
| 66 | 
            +
                    }
         | 
| 67 | 
            +
                    const { resourcePath, latestAsarPath } = this.availableUpdate;
         | 
| 68 | 
            +
                    const oldAsarPath = path_1.default.resolve(resourcePath, `${constants_1.OldArchivePrefix}${new Date().getTime()}.asar`);
         | 
| 69 | 
            +
                    const currentAsarPath = path_1.default.resolve(resourcePath, 'app.asar');
         | 
| 70 | 
            +
                    try {
         | 
| 71 | 
            +
                        // 将老包改名 app.asar => old-xxxx.asar
         | 
| 72 | 
            +
                        if (await (0, utils_1.existsAsync)(currentAsarPath)) {
         | 
| 73 | 
            +
                            await (0, utils_1.renameAsync)(currentAsarPath, oldAsarPath);
         | 
| 74 | 
            +
                        }
         | 
| 75 | 
            +
                    }
         | 
| 76 | 
            +
                    catch (error) {
         | 
| 77 | 
            +
                        return {
         | 
| 78 | 
            +
                            success: false,
         | 
| 79 | 
            +
                            error,
         | 
| 80 | 
            +
                        };
         | 
| 81 | 
            +
                    }
         | 
| 82 | 
            +
                    try {
         | 
| 83 | 
            +
                        // 新包替换
         | 
| 84 | 
            +
                        await (0, utils_1.renameAsync)(latestAsarPath, currentAsarPath);
         | 
| 85 | 
            +
                    }
         | 
| 86 | 
            +
                    catch (error) {
         | 
| 87 | 
            +
                        // 替换出错,需要把老包还原
         | 
| 88 | 
            +
                        await (0, utils_1.renameAsync)(oldAsarPath, currentAsarPath);
         | 
| 89 | 
            +
                        return {
         | 
| 90 | 
            +
                            success: false,
         | 
| 91 | 
            +
                            error,
         | 
| 92 | 
            +
                        };
         | 
| 93 | 
            +
                    }
         | 
| 94 | 
            +
                    this.logger.warn('AppUpdator#quitAndInstall:install success');
         | 
| 95 | 
            +
                    this.emit(constants_1.EventType.BEFORE_QUIT_FOR_UPDATE);
         | 
| 96 | 
            +
                    // 重启应用
         | 
| 97 | 
            +
                    this.app.relaunch();
         | 
| 98 | 
            +
                    return {
         | 
| 99 | 
            +
                        success: true,
         | 
| 100 | 
            +
                    };
         | 
| 101 | 
            +
                }
         | 
| 102 | 
            +
                async doQuitAndInstallPackage() {
         | 
| 103 | 
            +
                    this.logger.info('AppUpdator#doQuitAndInstallPackage:start');
         | 
| 104 | 
            +
                    return await (0, install_macos_dmg_1.default)(this.options, this.logger, this.availableUpdate, this.updateInfo);
         | 
| 105 | 
            +
                }
         | 
| 106 | 
            +
            }
         | 
| 107 | 
            +
            exports.MacUpdator = MacUpdator;
         | 
| 108 | 
            +
            //# sourceMappingURL=mac-updator.js.map
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            var __importDefault = (this && this.__importDefault) || function (mod) {
         | 
| 3 | 
            +
                return (mod && mod.__esModule) ? mod : { "default": mod };
         | 
| 4 | 
            +
            };
         | 
| 5 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 6 | 
            +
            exports.downloadFile = void 0;
         | 
| 7 | 
            +
            const urllib_1 = __importDefault(require("urllib"));
         | 
| 8 | 
            +
            const constants_1 = require("../common/constants");
         | 
| 9 | 
            +
            const _1 = require(".");
         | 
| 10 | 
            +
            /**
         | 
| 11 | 
            +
             * 文件下载
         | 
| 12 | 
            +
             * @param updator 更新实例
         | 
| 13 | 
            +
             * @param url 下载地址
         | 
| 14 | 
            +
             * @param signature 下载签名
         | 
| 15 | 
            +
             * @param targeDir 下载目录
         | 
| 16 | 
            +
             * @param progressHandle 下载状态回调
         | 
| 17 | 
            +
             * @return
         | 
| 18 | 
            +
             */
         | 
| 19 | 
            +
            const downloadFile = async ({ logger, url, signature, targetDir, progressHandle }) => {
         | 
| 20 | 
            +
                logger.info('downloadFile#downloadFile (start)');
         | 
| 21 | 
            +
                const writeStream = (0, _1.createWriteStream)(targetDir);
         | 
| 22 | 
            +
                let currentLength = 0;
         | 
| 23 | 
            +
                progressHandle({
         | 
| 24 | 
            +
                    status: constants_1.DownloadProgressStatus.Begin,
         | 
| 25 | 
            +
                });
         | 
| 26 | 
            +
                return new Promise((resolve, reject) => {
         | 
| 27 | 
            +
                    urllib_1.default
         | 
| 28 | 
            +
                        .request(url, {
         | 
| 29 | 
            +
                        streaming: true,
         | 
| 30 | 
            +
                        followRedirect: true,
         | 
| 31 | 
            +
                        timeout: 10 * 60 * 1000,
         | 
| 32 | 
            +
                    })
         | 
| 33 | 
            +
                        .then((res) => {
         | 
| 34 | 
            +
                        const totalLength = res.headers['content-length'];
         | 
| 35 | 
            +
                        logger.info(`downloadFile#downloadFile (then),totalLength is ${totalLength}`);
         | 
| 36 | 
            +
                        res.res.on('data', (data) => {
         | 
| 37 | 
            +
                            try {
         | 
| 38 | 
            +
                                currentLength += data.length;
         | 
| 39 | 
            +
                                const progress = (currentLength / totalLength) * 100;
         | 
| 40 | 
            +
                                progressHandle({
         | 
| 41 | 
            +
                                    status: constants_1.DownloadProgressStatus.Downloading,
         | 
| 42 | 
            +
                                    progress,
         | 
| 43 | 
            +
                                    url,
         | 
| 44 | 
            +
                                    signature,
         | 
| 45 | 
            +
                                    data,
         | 
| 46 | 
            +
                                });
         | 
| 47 | 
            +
                                writeStream.write(data);
         | 
| 48 | 
            +
                            }
         | 
| 49 | 
            +
                            catch (e) {
         | 
| 50 | 
            +
                                reject(e);
         | 
| 51 | 
            +
                            }
         | 
| 52 | 
            +
                        });
         | 
| 53 | 
            +
                        res.res.on('end', () => {
         | 
| 54 | 
            +
                            // 推迟调用 end(): https://stackoverflow.com/a/53878933
         | 
| 55 | 
            +
                            process.nextTick(() => writeStream.end());
         | 
| 56 | 
            +
                            try {
         | 
| 57 | 
            +
                                progressHandle({
         | 
| 58 | 
            +
                                    status: constants_1.DownloadProgressStatus.End,
         | 
| 59 | 
            +
                                    url,
         | 
| 60 | 
            +
                                    signature,
         | 
| 61 | 
            +
                                });
         | 
| 62 | 
            +
                                logger.info('download file success, url:%s, to %s', url, targetDir);
         | 
| 63 | 
            +
                                resolve();
         | 
| 64 | 
            +
                            }
         | 
| 65 | 
            +
                            catch (e) {
         | 
| 66 | 
            +
                                reject(e);
         | 
| 67 | 
            +
                            }
         | 
| 68 | 
            +
                        });
         | 
| 69 | 
            +
                        res.res.on('error', reject);
         | 
| 70 | 
            +
                    });
         | 
| 71 | 
            +
                });
         | 
| 72 | 
            +
            };
         | 
| 73 | 
            +
            exports.downloadFile = downloadFile;
         | 
| 74 | 
            +
            //# sourceMappingURL=download-file.js.map
         | 
| @@ -0,0 +1,122 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            var __importDefault = (this && this.__importDefault) || function (mod) {
         | 
| 3 | 
            +
                return (mod && mod.__esModule) ? mod : { "default": mod };
         | 
| 4 | 
            +
            };
         | 
| 5 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 6 | 
            +
            exports.getExecuteFile = exports.requestUpdateInfo = exports.existFile = exports.cleanOldArchive = exports.spawnAsync = exports.waitUntil = exports.sleep = exports.getMacOSAppPath = exports.sudoPrompt = exports.existsSync = exports.createWriteStream = exports.isMac = exports.isWin = exports.execAsync = exports.rimrafAsync = exports.readdirAsync = exports.existsAsync = exports.renameAsync = void 0;
         | 
| 7 | 
            +
            const path_1 = __importDefault(require("path"));
         | 
| 8 | 
            +
            const child_process_1 = require("child_process");
         | 
| 9 | 
            +
            const util_1 = __importDefault(require("util"));
         | 
| 10 | 
            +
            const urllib_1 = __importDefault(require("urllib"));
         | 
| 11 | 
            +
            const sudo_prompt_alt_1 = __importDefault(require("sudo-prompt-alt"));
         | 
| 12 | 
            +
            exports.sudoPrompt = sudo_prompt_alt_1.default;
         | 
| 13 | 
            +
            const rimraf_alt_1 = __importDefault(require("rimraf-alt"));
         | 
| 14 | 
            +
            const original_fs_1 = require("original-fs");
         | 
| 15 | 
            +
            Object.defineProperty(exports, "existsSync", { enumerable: true, get: function () { return original_fs_1.existsSync; } });
         | 
| 16 | 
            +
            Object.defineProperty(exports, "createWriteStream", { enumerable: true, get: function () { return original_fs_1.createWriteStream; } });
         | 
| 17 | 
            +
            const constants_1 = require("../common/constants");
         | 
| 18 | 
            +
            exports.renameAsync = util_1.default.promisify(original_fs_1.rename);
         | 
| 19 | 
            +
            exports.existsAsync = util_1.default.promisify(original_fs_1.exists);
         | 
| 20 | 
            +
            exports.readdirAsync = util_1.default.promisify(original_fs_1.readdir);
         | 
| 21 | 
            +
            exports.rimrafAsync = util_1.default.promisify(rimraf_alt_1.default);
         | 
| 22 | 
            +
            exports.execAsync = util_1.default.promisify(child_process_1.exec);
         | 
| 23 | 
            +
            exports.isWin = process.platform === 'win32';
         | 
| 24 | 
            +
            exports.isMac = process.platform === 'darwin';
         | 
| 25 | 
            +
            const getMacOSAppPath = () => {
         | 
| 26 | 
            +
                const sep = path_1.default.sep;
         | 
| 27 | 
            +
                const execPath = process.execPath;
         | 
| 28 | 
            +
                const contentPath = ['', 'Contents', 'MacOS'].join(sep);
         | 
| 29 | 
            +
                return execPath.split(contentPath)[0];
         | 
| 30 | 
            +
            };
         | 
| 31 | 
            +
            exports.getMacOSAppPath = getMacOSAppPath;
         | 
| 32 | 
            +
            const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
         | 
| 33 | 
            +
            exports.sleep = sleep;
         | 
| 34 | 
            +
            const waitUntil = async (handle, options = { retryTime: 10, ms: 1000 }) => {
         | 
| 35 | 
            +
                let retryTime = 0;
         | 
| 36 | 
            +
                const p = async () => {
         | 
| 37 | 
            +
                    const isOk = handle();
         | 
| 38 | 
            +
                    if (!isOk) {
         | 
| 39 | 
            +
                        if (retryTime === options.retryTime) {
         | 
| 40 | 
            +
                            return false;
         | 
| 41 | 
            +
                        }
         | 
| 42 | 
            +
                        retryTime++;
         | 
| 43 | 
            +
                        await (0, exports.sleep)(options.ms);
         | 
| 44 | 
            +
                        return await p();
         | 
| 45 | 
            +
                    }
         | 
| 46 | 
            +
                    return true;
         | 
| 47 | 
            +
                };
         | 
| 48 | 
            +
                return await p();
         | 
| 49 | 
            +
            };
         | 
| 50 | 
            +
            exports.waitUntil = waitUntil;
         | 
| 51 | 
            +
            const spawnAsync = (command, options) => {
         | 
| 52 | 
            +
                let stdout = '';
         | 
| 53 | 
            +
                let stderr = '';
         | 
| 54 | 
            +
                const child = (0, child_process_1.spawn)(command, options);
         | 
| 55 | 
            +
                child.stdout.on('data', (data) => {
         | 
| 56 | 
            +
                    stdout += data;
         | 
| 57 | 
            +
                });
         | 
| 58 | 
            +
                child.stderr.on('data', (data) => {
         | 
| 59 | 
            +
                    stderr += data;
         | 
| 60 | 
            +
                });
         | 
| 61 | 
            +
                return new Promise((resolve, reject) => {
         | 
| 62 | 
            +
                    child.on('error', reject);
         | 
| 63 | 
            +
                    child.on('close', (code) => {
         | 
| 64 | 
            +
                        if (code === 0) {
         | 
| 65 | 
            +
                            return resolve(stdout.toString());
         | 
| 66 | 
            +
                        }
         | 
| 67 | 
            +
                        const err = new Error(`child exited with code ${code}`);
         | 
| 68 | 
            +
                        err.code = code;
         | 
| 69 | 
            +
                        err.stderr = stderr.toString();
         | 
| 70 | 
            +
                        reject(err);
         | 
| 71 | 
            +
                    });
         | 
| 72 | 
            +
                });
         | 
| 73 | 
            +
            };
         | 
| 74 | 
            +
            exports.spawnAsync = spawnAsync;
         | 
| 75 | 
            +
            const cleanOldArchive = async (resourcePath) => {
         | 
| 76 | 
            +
                const resourceArray = await (0, exports.readdirAsync)(resourcePath);
         | 
| 77 | 
            +
                if (!resourceArray || !resourceArray.length) {
         | 
| 78 | 
            +
                    return;
         | 
| 79 | 
            +
                }
         | 
| 80 | 
            +
                const oldArchiveSource = resourceArray.filter((item) => item.startsWith(constants_1.OldArchivePrefix));
         | 
| 81 | 
            +
                return await Promise.all(oldArchiveSource.map(async (file) => {
         | 
| 82 | 
            +
                    const filePath = path_1.default.join(resourcePath, file);
         | 
| 83 | 
            +
                    if (await (0, exports.existsAsync)(filePath)) {
         | 
| 84 | 
            +
                        await (0, exports.rimrafAsync)(filePath);
         | 
| 85 | 
            +
                    }
         | 
| 86 | 
            +
                }));
         | 
| 87 | 
            +
            };
         | 
| 88 | 
            +
            exports.cleanOldArchive = cleanOldArchive;
         | 
| 89 | 
            +
            const existFile = async (path) => {
         | 
| 90 | 
            +
                const _existFile = await (0, exports.waitUntil)(() => (0, original_fs_1.existsSync)(path), {
         | 
| 91 | 
            +
                    ms: 1000,
         | 
| 92 | 
            +
                    retryTime: 30,
         | 
| 93 | 
            +
                });
         | 
| 94 | 
            +
                return _existFile;
         | 
| 95 | 
            +
            };
         | 
| 96 | 
            +
            exports.existFile = existFile;
         | 
| 97 | 
            +
            const requestUpdateInfo = async (options) => {
         | 
| 98 | 
            +
                const { url } = options;
         | 
| 99 | 
            +
                if (!url) {
         | 
| 100 | 
            +
                    throw new Error('request url can\'t be empty');
         | 
| 101 | 
            +
                }
         | 
| 102 | 
            +
                let res = null;
         | 
| 103 | 
            +
                try {
         | 
| 104 | 
            +
                    res = await urllib_1.default.request(url, {
         | 
| 105 | 
            +
                        dataType: 'json',
         | 
| 106 | 
            +
                        timeout: 10 * 1000,
         | 
| 107 | 
            +
                    });
         | 
| 108 | 
            +
                }
         | 
| 109 | 
            +
                catch (e) {
         | 
| 110 | 
            +
                    throw e;
         | 
| 111 | 
            +
                }
         | 
| 112 | 
            +
                if (!res || res.status !== 200) {
         | 
| 113 | 
            +
                    throw new Error(`request failure,status is ${res.status}`);
         | 
| 114 | 
            +
                }
         | 
| 115 | 
            +
                return res.data;
         | 
| 116 | 
            +
            };
         | 
| 117 | 
            +
            exports.requestUpdateInfo = requestUpdateInfo;
         | 
| 118 | 
            +
            const getExecuteFile = (file) => {
         | 
| 119 | 
            +
                return path_1.default.join(__dirname, '..', 'libs', file);
         | 
| 120 | 
            +
            };
         | 
| 121 | 
            +
            exports.getExecuteFile = getExecuteFile;
         | 
| 122 | 
            +
            //# sourceMappingURL=index.js.map
         | 
| @@ -0,0 +1,151 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            var __importDefault = (this && this.__importDefault) || function (mod) {
         | 
| 3 | 
            +
                return (mod && mod.__esModule) ? mod : { "default": mod };
         | 
| 4 | 
            +
            };
         | 
| 5 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 6 | 
            +
            const os_1 = __importDefault(require("os"));
         | 
| 7 | 
            +
            const path_1 = __importDefault(require("path"));
         | 
| 8 | 
            +
            const _1 = require(".");
         | 
| 9 | 
            +
            const index_1 = require("./index");
         | 
| 10 | 
            +
            const _log = (logger, e) => {
         | 
| 11 | 
            +
                const message = (e.stack || e).toString();
         | 
| 12 | 
            +
                logger.error?.(message);
         | 
| 13 | 
            +
            };
         | 
| 14 | 
            +
            exports.default = async (updatorOptions, logger, availableUpdate, updateInfo, preCheck = false) => {
         | 
| 15 | 
            +
                const { productName } = updatorOptions || {};
         | 
| 16 | 
            +
                const { downloadTargetDir } = availableUpdate || {};
         | 
| 17 | 
            +
                const appPath = (0, _1.getMacOSAppPath)();
         | 
| 18 | 
            +
                const tmpPath = path_1.default.join(os_1.default.tmpdir(), String(new Date().getTime())); // 本地临时文件使用的目录
         | 
| 19 | 
            +
                const volumesPath = path_1.default.join('/Volumes', updatorOptions.dmgTitleFormatter ? updatorOptions.dmgTitleFormatter(updatorOptions, updateInfo) : productName);
         | 
| 20 | 
            +
                const volumesAppPath = path_1.default.join(volumesPath, `${productName}.app`);
         | 
| 21 | 
            +
                // step 1: 检测是否支持 hdiutil;
         | 
| 22 | 
            +
                try {
         | 
| 23 | 
            +
                    const res = (await (0, index_1.spawnAsync)('which', ['hdiutil']));
         | 
| 24 | 
            +
                    if (!res.includes('/bin/hdiutil')) {
         | 
| 25 | 
            +
                        throw new Error('hdiutil not found');
         | 
| 26 | 
            +
                    }
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
                catch (error) {
         | 
| 29 | 
            +
                    if (preCheck) {
         | 
| 30 | 
            +
                        _log(logger, error);
         | 
| 31 | 
            +
                    }
         | 
| 32 | 
            +
                    return {
         | 
| 33 | 
            +
                        success: false,
         | 
| 34 | 
            +
                        error,
         | 
| 35 | 
            +
                    };
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
                // step 2: eject 一次 volume 下的 app,兜底,避免上一次结束时执行失败
         | 
| 38 | 
            +
                try {
         | 
| 39 | 
            +
                    await (0, index_1.spawnAsync)('hdiutil', ['eject', volumesPath]);
         | 
| 40 | 
            +
                }
         | 
| 41 | 
            +
                catch (e) {
         | 
| 42 | 
            +
                    // 如果前一次更新时 eject 成功,这里文件不存在会报错,是个正常的 case,不用处理上报
         | 
| 43 | 
            +
                }
         | 
| 44 | 
            +
                finally {
         | 
| 45 | 
            +
                    const volumeAppNotExist = await (0, _1.waitUntil)(() => !(0, index_1.existsSync)(volumesAppPath), {
         | 
| 46 | 
            +
                        ms: 300,
         | 
| 47 | 
            +
                        retryTime: 5,
         | 
| 48 | 
            +
                    });
         | 
| 49 | 
            +
                    if (!volumeAppNotExist) {
         | 
| 50 | 
            +
                        const error = new Error('volume not exists');
         | 
| 51 | 
            +
                        if (preCheck) {
         | 
| 52 | 
            +
                            _log(logger, error);
         | 
| 53 | 
            +
                        }
         | 
| 54 | 
            +
                        return {
         | 
| 55 | 
            +
                            success: false,
         | 
| 56 | 
            +
                            error,
         | 
| 57 | 
            +
                        };
         | 
| 58 | 
            +
                    }
         | 
| 59 | 
            +
                }
         | 
| 60 | 
            +
                // step 3: 执行 hdiutil attach,挂载 dmg
         | 
| 61 | 
            +
                try {
         | 
| 62 | 
            +
                    await (0, index_1.spawnAsync)('hdiutil', ['attach', downloadTargetDir]);
         | 
| 63 | 
            +
                }
         | 
| 64 | 
            +
                catch (error) {
         | 
| 65 | 
            +
                    _log(logger, error);
         | 
| 66 | 
            +
                }
         | 
| 67 | 
            +
                finally {
         | 
| 68 | 
            +
                    // 判断有没有新的 dmg 文件,没有的话提示用户重新下载
         | 
| 69 | 
            +
                    const volumeAppExist = await (0, _1.waitUntil)(() => (0, index_1.existsSync)(volumesAppPath), {
         | 
| 70 | 
            +
                        ms: 300,
         | 
| 71 | 
            +
                        retryTime: 5,
         | 
| 72 | 
            +
                    });
         | 
| 73 | 
            +
                    if (!volumeAppExist) {
         | 
| 74 | 
            +
                        const error = new Error('attach fail');
         | 
| 75 | 
            +
                        if (preCheck) {
         | 
| 76 | 
            +
                            _log(logger, error);
         | 
| 77 | 
            +
                        }
         | 
| 78 | 
            +
                        return {
         | 
| 79 | 
            +
                            success: false,
         | 
| 80 | 
            +
                            error,
         | 
| 81 | 
            +
                        };
         | 
| 82 | 
            +
                    }
         | 
| 83 | 
            +
                }
         | 
| 84 | 
            +
                if (preCheck) {
         | 
| 85 | 
            +
                    // 如果是预检查,直接返回
         | 
| 86 | 
            +
                    try {
         | 
| 87 | 
            +
                        await (0, index_1.spawnAsync)('hdiutil', ['eject', volumesPath]);
         | 
| 88 | 
            +
                    }
         | 
| 89 | 
            +
                    catch (error) {
         | 
| 90 | 
            +
                        _log(logger, error);
         | 
| 91 | 
            +
                    }
         | 
| 92 | 
            +
                    return {
         | 
| 93 | 
            +
                        success: true,
         | 
| 94 | 
            +
                    };
         | 
| 95 | 
            +
                }
         | 
| 96 | 
            +
                // step 4: 将当前目录下的 app 移到临时目录,如果后续操作失败了兜底用
         | 
| 97 | 
            +
                try {
         | 
| 98 | 
            +
                    await (0, index_1.spawnAsync)('mv', [appPath, tmpPath]);
         | 
| 99 | 
            +
                }
         | 
| 100 | 
            +
                catch (error) {
         | 
| 101 | 
            +
                    error.customMessage = 'step4 mv to tmp path error';
         | 
| 102 | 
            +
                    _log(logger, error);
         | 
| 103 | 
            +
                }
         | 
| 104 | 
            +
                finally {
         | 
| 105 | 
            +
                    // 看临时目录文件是否移动成功
         | 
| 106 | 
            +
                    const tmpPathExist = await (0, _1.waitUntil)(() => (0, index_1.existsSync)(tmpPath), {
         | 
| 107 | 
            +
                        ms: 300,
         | 
| 108 | 
            +
                        retryTime: 5,
         | 
| 109 | 
            +
                    });
         | 
| 110 | 
            +
                    if (!tmpPathExist) {
         | 
| 111 | 
            +
                        const error = new Error('cp to tmp path fail');
         | 
| 112 | 
            +
                        return {
         | 
| 113 | 
            +
                            success: false,
         | 
| 114 | 
            +
                            error,
         | 
| 115 | 
            +
                        };
         | 
| 116 | 
            +
                    }
         | 
| 117 | 
            +
                }
         | 
| 118 | 
            +
                // step 5: 将新的 app 文件移动到 Applications 目录下,如果失败 or 查不到移入文件,将临时目录下的文件移动回来
         | 
| 119 | 
            +
                try {
         | 
| 120 | 
            +
                    await (0, index_1.spawnAsync)('cp', ['-R', volumesAppPath, appPath]);
         | 
| 121 | 
            +
                }
         | 
| 122 | 
            +
                catch (error) {
         | 
| 123 | 
            +
                    _log(logger, error);
         | 
| 124 | 
            +
                }
         | 
| 125 | 
            +
                finally {
         | 
| 126 | 
            +
                    const appExist = await (0, _1.waitUntil)(() => (0, index_1.existsSync)(appPath), {
         | 
| 127 | 
            +
                        ms: 300,
         | 
| 128 | 
            +
                        retryTime: 5,
         | 
| 129 | 
            +
                    });
         | 
| 130 | 
            +
                    // 查不到新移入的 dmg,将原 dmg 再移动回来
         | 
| 131 | 
            +
                    if (!appExist) {
         | 
| 132 | 
            +
                        const error = new Error('cp to app fail');
         | 
| 133 | 
            +
                        await (0, index_1.spawnAsync)('mv', [tmpPath, appPath]);
         | 
| 134 | 
            +
                        return {
         | 
| 135 | 
            +
                            success: false,
         | 
| 136 | 
            +
                            error,
         | 
| 137 | 
            +
                        };
         | 
| 138 | 
            +
                    }
         | 
| 139 | 
            +
                }
         | 
| 140 | 
            +
                // step 6: 执行 hdiutil eject,推出
         | 
| 141 | 
            +
                try {
         | 
| 142 | 
            +
                    await (0, index_1.spawnAsync)('hdiutil', ['eject', volumesPath]);
         | 
| 143 | 
            +
                }
         | 
| 144 | 
            +
                catch (error) {
         | 
| 145 | 
            +
                    _log(logger, error);
         | 
| 146 | 
            +
                }
         | 
| 147 | 
            +
                return {
         | 
| 148 | 
            +
                    success: true,
         | 
| 149 | 
            +
                };
         | 
| 150 | 
            +
            };
         | 
| 151 | 
            +
            //# sourceMappingURL=install-macos-dmg.js.map
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 3 | 
            +
            exports.sudoPromptExec = void 0;
         | 
| 4 | 
            +
            const index_1 = require("./index");
         | 
| 5 | 
            +
            function sudoPromptExec(appUpdatorOptions, logger, shell) {
         | 
| 6 | 
            +
                const options = {
         | 
| 7 | 
            +
                    name: appUpdatorOptions.productName,
         | 
| 8 | 
            +
                };
         | 
| 9 | 
            +
                return new Promise((resolve, reject) => {
         | 
| 10 | 
            +
                    logger.warn(`update#sudoPromptExec_shell_${shell}`);
         | 
| 11 | 
            +
                    index_1.sudoPrompt.exec(shell, options, (error, stdout, _) => {
         | 
| 12 | 
            +
                        if (error) {
         | 
| 13 | 
            +
                            reject(error);
         | 
| 14 | 
            +
                            logger.error(`update#sudoPromptExec_error_${error}`);
         | 
| 15 | 
            +
                            return;
         | 
| 16 | 
            +
                        }
         | 
| 17 | 
            +
                        resolve(stdout);
         | 
| 18 | 
            +
                        logger.warn(`update#sudoPromptExec_stdout_${stdout}`);
         | 
| 19 | 
            +
                    });
         | 
| 20 | 
            +
                });
         | 
| 21 | 
            +
            }
         | 
| 22 | 
            +
            exports.sudoPromptExec = sudoPromptExec;
         | 
| 23 | 
            +
            //# sourceMappingURL=sudo-prompt-exec.js.map
         | 
| @@ -0,0 +1,87 @@ | |
| 1 | 
            +
            "use strict";
         | 
| 2 | 
            +
            var __importDefault = (this && this.__importDefault) || function (mod) {
         | 
| 3 | 
            +
                return (mod && mod.__esModule) ? mod : { "default": mod };
         | 
| 4 | 
            +
            };
         | 
| 5 | 
            +
            Object.defineProperty(exports, "__esModule", { value: true });
         | 
| 6 | 
            +
            exports.WindowsUpdator = void 0;
         | 
| 7 | 
            +
            const path_1 = __importDefault(require("path"));
         | 
| 8 | 
            +
            const electron_1 = require("electron");
         | 
| 9 | 
            +
            const constants_1 = require("./common/constants");
         | 
| 10 | 
            +
            const sudo_prompt_exec_1 = require("./utils/sudo-prompt-exec");
         | 
| 11 | 
            +
            const app_updator_1 = require("./app-updator");
         | 
| 12 | 
            +
            const utils_1 = require("./utils");
         | 
| 13 | 
            +
            class WindowsUpdator extends app_updator_1.AppUpdator {
         | 
| 14 | 
            +
                doGetAvailableUpdateInfo(updateInfo) {
         | 
| 15 | 
            +
                    this.logger.info(`WindowsUpdator#doGetAvailableUpdateInfo:start`);
         | 
| 16 | 
            +
                    let resourcePath = path_1.default.resolve(this.app.userDataPath);
         | 
| 17 | 
            +
                    const latestAsarPath = path_1.default.resolve(resourcePath, 'latest.asar');
         | 
| 18 | 
            +
                    const latestAppPath = path_1.default.resolve(resourcePath, 'latest');
         | 
| 19 | 
            +
                    let downloadTargetDir = `${latestAsarPath}.zip`;
         | 
| 20 | 
            +
                    if (updateInfo.updateType === constants_1.UpdateType.Package) {
         | 
| 21 | 
            +
                        downloadTargetDir = `${latestAppPath}.exe`;
         | 
| 22 | 
            +
                    }
         | 
| 23 | 
            +
                    return {
         | 
| 24 | 
            +
                        resourcePath,
         | 
| 25 | 
            +
                        downloadTargetDir,
         | 
| 26 | 
            +
                        latestAsarPath,
         | 
| 27 | 
            +
                    };
         | 
| 28 | 
            +
                }
         | 
| 29 | 
            +
                async doPreCheckForPackage() {
         | 
| 30 | 
            +
                    this.logger.info(`WindowsUpdator#doPreCheckForPackage:start`);
         | 
| 31 | 
            +
                    // Windows 全量安装默认预检正常
         | 
| 32 | 
            +
                    return Promise.resolve({ success: true });
         | 
| 33 | 
            +
                }
         | 
| 34 | 
            +
                async doUnzip() {
         | 
| 35 | 
            +
                    this.logger.info(`WindowsUpdator#doUnzip:start`);
         | 
| 36 | 
            +
                    try {
         | 
| 37 | 
            +
                        const { downloadTargetDir, resourcePath } = this.availableUpdate;
         | 
| 38 | 
            +
                        const unzipExe = (0, utils_1.getExecuteFile)('unzip.exe');
         | 
| 39 | 
            +
                        const executeCommand = `"${unzipExe}" -o "${downloadTargetDir}" -d "${resourcePath}"`;
         | 
| 40 | 
            +
                        await (0, utils_1.execAsync)(executeCommand);
         | 
| 41 | 
            +
                    }
         | 
| 42 | 
            +
                    catch (error) {
         | 
| 43 | 
            +
                        return {
         | 
| 44 | 
            +
                            success: false,
         | 
| 45 | 
            +
                            error,
         | 
| 46 | 
            +
                        };
         | 
| 47 | 
            +
                    }
         | 
| 48 | 
            +
                    this.logger.info(`WindowsUpdator#doUnzip:success`);
         | 
| 49 | 
            +
                    return {
         | 
| 50 | 
            +
                        success: true,
         | 
| 51 | 
            +
                    };
         | 
| 52 | 
            +
                }
         | 
| 53 | 
            +
                async doQuitAndInstallPackage() {
         | 
| 54 | 
            +
                    this.logger.info(`WindowsUpdator#doQuitAndInstallPackage:success`);
         | 
| 55 | 
            +
                    const { downloadTargetDir } = this.availableUpdate;
         | 
| 56 | 
            +
                    try {
         | 
| 57 | 
            +
                        // Windows 全量安装
         | 
| 58 | 
            +
                        const shellOpen = electron_1.shell.openItem || electron_1.shell.openPath;
         | 
| 59 | 
            +
                        shellOpen(downloadTargetDir);
         | 
| 60 | 
            +
                        setTimeout(() => {
         | 
| 61 | 
            +
                            this.app.exit(0);
         | 
| 62 | 
            +
                        }, 30);
         | 
| 63 | 
            +
                        return Promise.resolve({ success: true });
         | 
| 64 | 
            +
                    }
         | 
| 65 | 
            +
                    catch (error) {
         | 
| 66 | 
            +
                        return Promise.resolve({ success: false, error });
         | 
| 67 | 
            +
                    }
         | 
| 68 | 
            +
                }
         | 
| 69 | 
            +
                async doQuitAndInstallAsar() {
         | 
| 70 | 
            +
                    this.logger.info(`WindowsUpdator#doQuitAndInstallAsar:start`);
         | 
| 71 | 
            +
                    const productName = this.options?.productName;
         | 
| 72 | 
            +
                    const { resourcePath } = this.availableUpdate;
         | 
| 73 | 
            +
                    const exePath = this.app.exePath;
         | 
| 74 | 
            +
                    const updateExePath = (0, utils_1.getExecuteFile)('installer.exe');
         | 
| 75 | 
            +
                    const targetPath = path_1.default.resolve(exePath, '..', 'resources');
         | 
| 76 | 
            +
                    const executeCommand = `"${updateExePath}" "${targetPath}" "${resourcePath}" "${productName}.exe" "${exePath}"`;
         | 
| 77 | 
            +
                    try {
         | 
| 78 | 
            +
                        await (0, sudo_prompt_exec_1.sudoPromptExec)(this.options, this.logger, executeCommand);
         | 
| 79 | 
            +
                        return Promise.resolve({ success: true });
         | 
| 80 | 
            +
                    }
         | 
| 81 | 
            +
                    catch (error) {
         | 
| 82 | 
            +
                        return Promise.resolve({ success: false, error });
         | 
| 83 | 
            +
                    }
         | 
| 84 | 
            +
                }
         | 
| 85 | 
            +
            }
         | 
| 86 | 
            +
            exports.WindowsUpdator = WindowsUpdator;
         | 
| 87 | 
            +
            //# sourceMappingURL=windows-updator.js.map
         | 
    
        package/package.json
    CHANGED
    
    | @@ -1,34 +1,65 @@ | |
| 1 1 | 
             
            {
         | 
| 2 2 | 
             
              "name": "electron-updator",
         | 
| 3 | 
            -
              "version": "0.1. | 
| 4 | 
            -
              "description": "electron-updator",
         | 
| 5 | 
            -
              " | 
| 6 | 
            -
             | 
| 7 | 
            -
                " | 
| 3 | 
            +
              "version": "0.1.3",
         | 
| 4 | 
            +
              "description": "electron-updator is a software updator management solution for Electron applications, It is convenient to complete full software update and dynamic update.",
         | 
| 5 | 
            +
              "scripts": {
         | 
| 6 | 
            +
                "build": "sh ./build.sh",
         | 
| 7 | 
            +
                "test": "egg-bin test test/**/index.test.ts",
         | 
| 8 | 
            +
                "lint": "eslint --fix --quiet --ext .js,.jsx ./src",
         | 
| 9 | 
            +
                "prepublishOnly": "npm run build",
         | 
| 10 | 
            +
                "contributor": "git-contributor",
         | 
| 11 | 
            +
                "dev": "ttsc -p tsconfig.json -watch"
         | 
| 8 12 | 
             
              },
         | 
| 13 | 
            +
              "main": "./build",
         | 
| 14 | 
            +
              "keywords": [
         | 
| 15 | 
            +
                "electron",
         | 
| 16 | 
            +
                "updator",
         | 
| 17 | 
            +
                "auto-updator"
         | 
| 18 | 
            +
              ],
         | 
| 9 19 | 
             
              "files": [
         | 
| 10 | 
            -
                " | 
| 11 | 
            -
                " | 
| 20 | 
            +
                "build/**/*.js",
         | 
| 21 | 
            +
                "build/**/*.exe"
         | 
| 12 22 | 
             
              ],
         | 
| 13 | 
            -
              "main": "index.js",
         | 
| 14 23 | 
             
              "repository": {
         | 
| 15 24 | 
             
                "type": "git",
         | 
| 16 | 
            -
                "url": " | 
| 25 | 
            +
                "url": "https://github.com/electron-modules/electron-updator"
         | 
| 17 26 | 
             
              },
         | 
| 18 27 | 
             
              "dependencies": {
         | 
| 28 | 
            +
                "eventemitter3": "^4.0.0",
         | 
| 29 | 
            +
                "lodash": "4.17.21",
         | 
| 30 | 
            +
                "moment": "2.29.4",
         | 
| 31 | 
            +
                "rimraf-alt": "*",
         | 
| 32 | 
            +
                "sudo-prompt-alt": "9",
         | 
| 33 | 
            +
                "urllib": "2.34.1"
         | 
| 19 34 | 
             
              },
         | 
| 20 35 | 
             
              "devDependencies": {
         | 
| 21 | 
            -
                " | 
| 22 | 
            -
                " | 
| 23 | 
            -
                " | 
| 24 | 
            -
                " | 
| 25 | 
            -
                " | 
| 26 | 
            -
                " | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
                " | 
| 30 | 
            -
                " | 
| 31 | 
            -
                " | 
| 36 | 
            +
                "@applint/spec": "^1.2.0",
         | 
| 37 | 
            +
                "@types/lodash": "^4.14.181",
         | 
| 38 | 
            +
                "@types/mocha": "^10.0.1",
         | 
| 39 | 
            +
                "@types/mock-require": "^2.0.1",
         | 
| 40 | 
            +
                "@types/react-dom": "^17.0.16",
         | 
| 41 | 
            +
                "@typescript-eslint/parser": "^5.19.0",
         | 
| 42 | 
            +
                "babel-plugin-module-resolver": "^4.1.0",
         | 
| 43 | 
            +
                "concurrently": "^5.3.0",
         | 
| 44 | 
            +
                "copyfiles": "^2.4.1",
         | 
| 45 | 
            +
                "cross-env": "^7.0.3",
         | 
| 46 | 
            +
                "detect-port": "1",
         | 
| 47 | 
            +
                "egg-bin": "^5.9.0",
         | 
| 48 | 
            +
                "electron": "18",
         | 
| 49 | 
            +
                "electron-windows": "18",
         | 
| 50 | 
            +
                "eslint": "^7.32.0",
         | 
| 51 | 
            +
                "git-contributor": "*",
         | 
| 52 | 
            +
                "husky": "^7.0.4",
         | 
| 53 | 
            +
                "mm": "^3.0.2",
         | 
| 54 | 
            +
                "mock-require": "^3.0.3",
         | 
| 55 | 
            +
                "prettier": "^2.6.2",
         | 
| 56 | 
            +
                "prop-types": "^15.7.2",
         | 
| 57 | 
            +
                "style-loader": "^1.1.2",
         | 
| 58 | 
            +
                "ts-loader": "^9.2.8",
         | 
| 59 | 
            +
                "ts-node": "^10.7.0",
         | 
| 60 | 
            +
                "ttypescript": "^1.5.15",
         | 
| 61 | 
            +
                "typescript": "^4.6.3",
         | 
| 62 | 
            +
                "typescript-transform-paths": "^3.3.1"
         | 
| 32 63 | 
             
              },
         | 
| 33 64 | 
             
              "husky": {
         | 
| 34 65 | 
             
                "hooks": {
         | 
    
        package/bin/electron-updator.js
    DELETED
    
    
    
        package/index.js
    DELETED
    
    
    
        package/lib/electron-updator.js
    DELETED
    
    | @@ -1 +0,0 @@ | |
| 1 | 
            -
            'use strict';
         |